720 lines
20 KiB
Go
720 lines
20 KiB
Go
package fsplParser
|
|
|
|
import "git.tebibyte.media/fspl/fspl/lexer"
|
|
import "git.tebibyte.media/fspl/fspl/errors"
|
|
import "git.tebibyte.media/fspl/fspl/entity"
|
|
|
|
var descriptionExpression = "expression"
|
|
var startTokensExpression = []lexer.TokenKind {
|
|
lexer.Ident,
|
|
lexer.LParen,
|
|
lexer.LBracket,
|
|
lexer.LBrace,
|
|
lexer.Int,
|
|
lexer.Float,
|
|
lexer.String,
|
|
}
|
|
|
|
func (this *treeParser) parseExpression () (entity.Expression, error) {
|
|
// Steps that this function takes to parse expressions:
|
|
// 1. Run a decision tree to parse the expression.
|
|
// 2. After that, test for infix operators (. and =). We will not need
|
|
// to consume more tokens to do this, as if they exist they will be
|
|
// the very next token AKA the current one after parsing the
|
|
// expression.
|
|
// 3. Then, use the previously parsed expression and use it as the left
|
|
// side, and go on to parse the right side. Assignment (=) is the
|
|
// only infix expression where both left and right sides are
|
|
// expressions, so it gets to call parseExpression() and recurse. The
|
|
// implied associativity matters here.
|
|
// 4. If not assignment, then this has to do with member access (the
|
|
// right side is not an expression), so we repeat from step 2 in order
|
|
// to chain member accesses and method calls. Step 2 will test
|
|
// whether or not we need to continue repeating afterward. The
|
|
// implied associativity matters here.
|
|
// 5. Return the expression, whether it was directly parsed or is a tree
|
|
// of infix operator(s).
|
|
|
|
// run decision tree
|
|
expression, err := this.parseExpressionRoot()
|
|
if err != nil { return nil, err }
|
|
|
|
// test for infix operators
|
|
for this.Token.Is(lexer.Dot) || (this.Token.Is(lexer.Symbol) && this.Token.ValueIs("=")) {
|
|
pos := this.Pos()
|
|
|
|
switch this.Kind() {
|
|
case lexer.Dot:
|
|
// Dot: member access or method call
|
|
// this control path must not return, staying within the
|
|
// loop
|
|
source := expression
|
|
err := this.ExpectNextDesc (
|
|
"member access or method call",
|
|
lexer.Ident, lexer.LBracket)
|
|
if err != nil { return nil, err }
|
|
|
|
switch this.Kind() {
|
|
case lexer.Ident:
|
|
// Ident: member access
|
|
expression = &entity.MemberAccess {
|
|
Pos: pos.Union(this.Pos()),
|
|
Source: source,
|
|
Member: this.Value(),
|
|
}
|
|
this.Next()
|
|
|
|
case lexer.LBracket:
|
|
// LBracket: method call
|
|
expression, err = this.parseMethodCallCore(pos, source)
|
|
if err != nil { return nil, err }
|
|
}
|
|
|
|
case lexer.Symbol:
|
|
// Symbol '=': assignment
|
|
// this control path must return, breaking out of the
|
|
// loop.
|
|
expression := &entity.Assignment {
|
|
Pos: pos,
|
|
Location: expression,
|
|
}
|
|
|
|
this.Next()
|
|
value, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
expression.Value = value
|
|
return expression, nil
|
|
}
|
|
}
|
|
|
|
return expression, nil
|
|
}
|
|
|
|
func (this *treeParser) parseExpressionRoot () (entity.Expression, error) {
|
|
err := this.ExpectDesc(descriptionExpression, startTokensExpression...)
|
|
if err != nil { return nil, err }
|
|
|
|
switch this.Kind() {
|
|
case lexer.Ident: return this.parseExpressionRootIdent()
|
|
case lexer.LParen: return this.parseExpressionRootLParen()
|
|
case lexer.LBracket: return this.parseExpressionRootLBracket()
|
|
case lexer.LBrace: return this.parseBlock()
|
|
case lexer.Int: return this.parseLiteralInt()
|
|
case lexer.Float: return this.parseLiteralFloat()
|
|
case lexer.String: return this.parseLiteralString()
|
|
}
|
|
panic(this.bug())
|
|
}
|
|
|
|
func (this *treeParser) parseExpressionRootIdent () (entity.Expression, error) {
|
|
err := this.Expect(lexer.Ident)
|
|
if err != nil { return nil, err }
|
|
name := this.Value()
|
|
pos := this.Pos()
|
|
|
|
switch name {
|
|
case "true", "false": return this.parseLiteralBoolean ()
|
|
case "nil": return this.parseLiteralNil()
|
|
case "if": return this.parseIfElse()
|
|
case "match": return this.parseMatch()
|
|
case "switch": return this.parseSwitch()
|
|
case "loop": return this.parseLoop()
|
|
case "for": return this.parseFor()
|
|
default:
|
|
this.Next()
|
|
switch this.Kind() {
|
|
case lexer.Colon:
|
|
// Colon: declaration
|
|
return this.parseDeclarationCore(pos, name)
|
|
case lexer.DoubleColon:
|
|
// DoubleColon: call
|
|
err := this.ExpectNext(lexer.LBracket)
|
|
if err != nil { return nil, err }
|
|
this.Next()
|
|
return this.parseCallCore(pos, name)
|
|
default:
|
|
// *: variable
|
|
return &entity.Variable {
|
|
Pos: pos,
|
|
Name: name,
|
|
}, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *treeParser) parseExpressionRootLParen () (entity.Expression, error) {
|
|
err := this.Expect(lexer.LParen)
|
|
if err != nil { return nil, err }
|
|
pos := this.Pos()
|
|
|
|
err = this.ExpectNextDesc (
|
|
"struct or array literal",
|
|
appendCopy(startTokensExpression, lexer.Dot)...)
|
|
if err != nil { return nil, err }
|
|
switch this.Kind() {
|
|
case lexer.Dot: return this.parseLiteralStructCore(pos)
|
|
default: return this.parseLiteralArrayCore(pos)
|
|
}
|
|
panic(this.bug())
|
|
}
|
|
|
|
func (this *treeParser) parseExpressionRootLBracket () (entity.Expression, error) {
|
|
err := this.Expect(lexer.LBracket)
|
|
if err != nil { return nil, err }
|
|
pos := this.Pos()
|
|
|
|
err = this.ExpectNext(lexer.Ident, lexer.Dot, lexer.Star, lexer.Symbol)
|
|
if err != nil { return nil, err }
|
|
switch this.Kind() {
|
|
case lexer.Ident: return this.parseExpressionRootLBracketIdent(pos)
|
|
case lexer.Dot: return this.parseDereferenceOrSubscriptCore(pos)
|
|
case lexer.Star: return this.parseOperationCore(pos)
|
|
case lexer.Symbol: return this.parseExpressionRootLBracketSymbol(pos)
|
|
}
|
|
panic(this.bug())
|
|
}
|
|
|
|
func (this *treeParser) parseExpressionRootLBracketIdent (pos errors.Position) (entity.Expression, error) {
|
|
err := this.Expect(lexer.Ident)
|
|
if err != nil { return nil, err }
|
|
name := this.Value()
|
|
|
|
switch name {
|
|
case "break", "return": return this.parseReturnOrBreakCore(pos)
|
|
default: return this.parseCallCore(pos, "")
|
|
}
|
|
}
|
|
|
|
func (this *treeParser) parseDereferenceOrSubscriptCore (pos errors.Position) (entity.Expression, error) {
|
|
err := this.Expect(lexer.Dot)
|
|
if err != nil { return nil, err }
|
|
|
|
this.Next()
|
|
argument, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
err = this.ExpectDesc (
|
|
"element offset expression or end of dereference",
|
|
appendCopy(startTokensExpression, lexer.RBracket)...)
|
|
if err != nil { return nil, err }
|
|
|
|
if this.Token.Is(lexer.RBracket) {
|
|
// RBracket: dereference
|
|
pos = pos.Union(this.Pos())
|
|
this.Next()
|
|
|
|
return &entity.Dereference {
|
|
Pos: pos,
|
|
Pointer: argument,
|
|
}, nil
|
|
} else {
|
|
// startTokensExpression...: subscript
|
|
offset, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
err = this.Expect(lexer.RBracket)
|
|
if err != nil { return nil, err }
|
|
pos = pos.Union(this.Pos())
|
|
this.Next()
|
|
|
|
return &entity.Subscript {
|
|
Pos: pos,
|
|
Slice: argument,
|
|
Offset: offset,
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func (this *treeParser) parseExpressionRootLBracketSymbol (pos errors.Position) (entity.Expression, error) {
|
|
err := this.ExpectValue (
|
|
lexer.Symbol,
|
|
appendCopy(valuesOperator, "\\", "#", "@", "~", "~~")...)
|
|
if err != nil { return nil, err }
|
|
|
|
switch this.Value() {
|
|
case "\\": return this.parseSliceCore(pos)
|
|
case "#": return this.parseLengthCore(pos)
|
|
case "@": return this.parseReferenceCore(pos)
|
|
case "~": return this.parseValueOrBitCastCore(pos)
|
|
case "~~": return this.parseValueOrBitCastCore(pos)
|
|
default: return this.parseOperationCore(pos)
|
|
}
|
|
}
|
|
|
|
func (this *treeParser) parseCallCore (pos errors.Position, unitNickname string) (*entity.Call, error) {
|
|
err := this.Expect(lexer.Ident)
|
|
if err != nil { return nil, err }
|
|
call := &entity.Call {
|
|
Pos: pos,
|
|
UnitNickname: unitNickname,
|
|
Name: this.Value(),
|
|
}
|
|
this.Next()
|
|
|
|
for {
|
|
err = this.ExpectDesc (
|
|
"argument or end of call",
|
|
appendCopy(startTokensExpression, lexer.RBracket)...)
|
|
if err != nil { return nil, err }
|
|
if this.Token.Is(lexer.RBracket) { break }
|
|
|
|
argument, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
call.Arguments = append(call.Arguments, argument)
|
|
}
|
|
call.Pos = call.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return call, nil
|
|
}
|
|
|
|
func (this *treeParser) parseMethodCallCore (pos errors.Position, source entity.Expression) (*entity.MethodCall, error) {
|
|
err := this.Expect(lexer.LBracket)
|
|
if err != nil { return nil, err }
|
|
err = this.ExpectNext(lexer.Ident)
|
|
if err != nil { return nil, err }
|
|
call := &entity.MethodCall {
|
|
Source: source,
|
|
Pos: pos,
|
|
Name: this.Value(),
|
|
}
|
|
this.Next()
|
|
|
|
for {
|
|
err = this.ExpectDesc (
|
|
"argument or end of method call",
|
|
appendCopy(startTokensExpression, lexer.RBracket)...)
|
|
if err != nil { return nil, err }
|
|
if this.Token.Is(lexer.RBracket) { break }
|
|
|
|
argument, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
call.Arguments = append(call.Arguments, argument)
|
|
}
|
|
call.Pos = call.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return call, nil
|
|
}
|
|
|
|
func (this *treeParser) parseReturnOrBreakCore (pos errors.Position) (entity.Expression, error) {
|
|
err := this.ExpectValue(lexer.Ident, "break", "return")
|
|
if err != nil { return nil, err }
|
|
name := this.Value()
|
|
|
|
err = this.ExpectNextDesc (
|
|
"expression or end of " + name,
|
|
appendCopy(startTokensExpression, lexer.RBracket)...)
|
|
if err != nil { return nil, err }
|
|
var value entity.Expression
|
|
if this.Token.Is(startTokensExpression...) {
|
|
// startTokensExpression...: value expression
|
|
value, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
}
|
|
|
|
err = this.ExpectDesc("end of " + name, lexer.RBracket)
|
|
if err != nil { return nil, err }
|
|
pos = pos.Union(this.Pos())
|
|
this.Next()
|
|
|
|
switch name {
|
|
case "break":
|
|
return &entity.Break {
|
|
Pos: pos,
|
|
Value: value,
|
|
}, nil
|
|
case "return":
|
|
return &entity.Return {
|
|
Pos: pos,
|
|
Value: value,
|
|
}, nil
|
|
}
|
|
panic(this.bug())
|
|
}
|
|
|
|
func (this *treeParser) parseSliceCore (pos errors.Position) (*entity.Slice, error) {
|
|
err := this.ExpectValue(lexer.Symbol , "\\")
|
|
if err != nil { return nil, err }
|
|
slice := &entity.Slice {
|
|
Pos: pos,
|
|
}
|
|
|
|
err = this.ExpectNextDesc(descriptionExpression, startTokensExpression...)
|
|
if err != nil { return nil, err }
|
|
slice.Slice, err = this.parseExpression()
|
|
|
|
err = this.ExpectDesc (
|
|
"offset expression or '/'",
|
|
appendCopy(startTokensExpression, lexer.Symbol)...)
|
|
if err != nil { return nil, err }
|
|
if this.Token.Is(startTokensExpression...) {
|
|
// startTokensExpression...: starting offset
|
|
slice.Start, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
}
|
|
|
|
err = this.ExpectValue(lexer.Symbol, "/")
|
|
if err != nil { return nil, err }
|
|
|
|
this.ExpectNextDesc (
|
|
"offset expression or operation end",
|
|
appendCopy(startTokensExpression, lexer.RBracket)...)
|
|
if this.Token.Is(startTokensExpression...) {
|
|
// startTokensExpression...: ending offset
|
|
slice.End, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
}
|
|
|
|
err = this.Expect(lexer.RBracket)
|
|
if err != nil { return nil, err }
|
|
slice.Pos = slice.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return slice, nil
|
|
}
|
|
|
|
func (this *treeParser) parseLengthCore (pos errors.Position) (*entity.Length, error) {
|
|
err := this.ExpectValue(lexer.Symbol , "#")
|
|
if err != nil { return nil, err }
|
|
length := &entity.Length {
|
|
Pos: pos,
|
|
}
|
|
|
|
this.Next()
|
|
length.Slice, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
err = this.Expect(lexer.RBracket)
|
|
if err != nil { return nil, err }
|
|
length.Pos = length.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return length, nil
|
|
}
|
|
|
|
func (this *treeParser) parseReferenceCore (pos errors.Position) (*entity.Reference, error) {
|
|
err := this.ExpectValue(lexer.Symbol , "@")
|
|
if err != nil { return nil, err }
|
|
reference := &entity.Reference {
|
|
Pos: pos,
|
|
}
|
|
|
|
this.Next()
|
|
reference.Value, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
err = this.Expect(lexer.RBracket)
|
|
if err != nil { return nil, err }
|
|
reference.Pos = reference.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return reference, nil
|
|
}
|
|
|
|
func (this *treeParser) parseValueOrBitCastCore (pos errors.Position) (entity.Expression, error) {
|
|
err := this.ExpectValue(lexer.Symbol , "~", "~~")
|
|
if err != nil { return nil, err }
|
|
tokValue := this.Value()
|
|
|
|
this.Next()
|
|
ty, err := this.parseType()
|
|
if err != nil { return nil, err }
|
|
|
|
err = this.ExpectDesc(descriptionExpression, startTokensExpression...)
|
|
if err != nil { return nil, err }
|
|
value, err := this.parseExpression()
|
|
|
|
err = this.Expect(lexer.RBracket)
|
|
if err != nil { return nil, err }
|
|
pos = pos.Union(this.Pos())
|
|
this.Next()
|
|
|
|
switch tokValue {
|
|
case "~":
|
|
return &entity.ValueCast {
|
|
Pos: pos,
|
|
Ty: ty,
|
|
Value: value,
|
|
}, nil
|
|
case "~~":
|
|
return &entity.BitCast {
|
|
Pos: pos,
|
|
Ty: ty,
|
|
Value: value,
|
|
}, nil
|
|
}
|
|
panic(this.bug())
|
|
}
|
|
|
|
var valuesOperator = []string {
|
|
"++", "+", "--", "-", "*", "/", "%", "!!", "||", "&&", "^^",
|
|
"!", "|", "&", "^", "<<", ">>", "<", ">", "<=", ">=", "=",
|
|
}
|
|
|
|
func (this *treeParser) parseOperationCore (pos errors.Position) (*entity.Operation, error) {
|
|
// TODO: maybe come up with a more elegant way of writing this?
|
|
// possibly make a verion of expectValue that matches a list of kinds
|
|
// and a list of values. could also make a version that accepts any kind
|
|
// of token, and always supplement that with a normal expect.
|
|
if this.Token.Is(lexer.Star) {
|
|
err := this.ExpectValue(lexer.Star, valuesOperator...)
|
|
if err != nil { return nil, err }
|
|
} else {
|
|
err := this.ExpectValue(lexer.Symbol, valuesOperator...)
|
|
if err != nil { return nil, err }
|
|
}
|
|
|
|
operation := &entity.Operation {
|
|
Pos: pos,
|
|
Operator: entity.OperatorFromString(this.Value()),
|
|
}
|
|
this.Next()
|
|
|
|
for {
|
|
err := this.ExpectDesc (
|
|
"expression or operation end",
|
|
appendCopy(startTokensExpression, lexer.RBracket)...)
|
|
if err != nil { return nil, err }
|
|
if this.Token.Is(lexer.RBracket) { break }
|
|
|
|
argument, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
operation.Arguments = append(operation.Arguments, argument)
|
|
}
|
|
operation.Pos = operation.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return operation, nil
|
|
}
|
|
|
|
func (this *treeParser) parseBlock () (*entity.Block, error) {
|
|
err := this.ExpectDesc("Block", lexer.LBrace)
|
|
if err != nil { return nil, err }
|
|
block := &entity.Block {
|
|
Pos: this.Pos(),
|
|
}
|
|
this.Next()
|
|
|
|
for {
|
|
err := this.ExpectDesc (
|
|
descriptionExpression,
|
|
appendCopy(startTokensExpression, lexer.RBrace)...)
|
|
if err != nil { return nil, err }
|
|
if this.Kind() == lexer.RBrace{ break }
|
|
|
|
step, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
block.Steps = append(block.Steps, step)
|
|
}
|
|
block.Pos = block.Position().Union(this.Pos())
|
|
this.Next()
|
|
|
|
return block, nil
|
|
}
|
|
|
|
var descriptionDeclaration = "declaration"
|
|
var startTokensDeclaration = []lexer.TokenKind { lexer.Ident }
|
|
|
|
func (this *treeParser) parseDeclaration () (*entity.Declaration, error) {
|
|
err := this.ExpectDesc(descriptionDeclaration, startTokensDeclaration...)
|
|
if err != nil { return nil, err }
|
|
name := this.Value()
|
|
pos := this.Pos()
|
|
this.Next()
|
|
return this.parseDeclarationCore(pos, name)
|
|
}
|
|
|
|
func (this *treeParser) parseDeclarationCore (pos errors.Position, name string) (*entity.Declaration, error) {
|
|
err := this.Expect(lexer.Colon)
|
|
if err != nil { return nil, err }
|
|
this.Next()
|
|
ty, err := this.parseType()
|
|
if err != nil { return nil, err }
|
|
|
|
return &entity.Declaration {
|
|
Pos: pos,
|
|
Name: name,
|
|
Ty: ty,
|
|
}, nil
|
|
}
|
|
|
|
func (this *treeParser) parseIfElse () (*entity.IfElse, error) {
|
|
err := this.ExpectValue(lexer.Ident, "if")
|
|
if err != nil { return nil, err }
|
|
ifElse := &entity.IfElse {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
err = this.ExpectNextDesc("condition", startTokensExpression...)
|
|
if err != nil { return nil, err }
|
|
ifElse.Condition, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
err = this.ExpectValue(lexer.Ident, "then")
|
|
if err != nil { return nil, err }
|
|
|
|
this.ExpectNextDesc("branch expression", startTokensExpression...)
|
|
ifElse.True, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
if this.Token.Is(lexer.Ident) && this.Token.ValueIs("else") {
|
|
// Ident "else": false branch expression
|
|
this.ExpectNextDesc("branch expression", startTokensExpression...)
|
|
ifElse.False, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
}
|
|
|
|
return ifElse, nil
|
|
}
|
|
|
|
func (this *treeParser) parseMatch () (*entity.Match, error) {
|
|
err := this.ExpectValue(lexer.Ident, "match")
|
|
if err != nil { return nil, err }
|
|
match := &entity.Match {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
err = this.ExpectNextDesc(descriptionExpression, startTokensExpression...)
|
|
if err != nil { return nil, err }
|
|
match.Value, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
for this.Is(lexer.Symbol) && this.ValueIs("|") {
|
|
cas, err := this.parseMatchCase()
|
|
if err != nil { return nil, err }
|
|
match.Cases = append(match.Cases, cas)
|
|
}
|
|
|
|
if this.Is(lexer.Star) {
|
|
defaul, err := this.parseDefaultCase()
|
|
if err != nil { return nil, err }
|
|
match.Default = defaul
|
|
}
|
|
|
|
return match, nil
|
|
}
|
|
|
|
func (this *treeParser) parseMatchCase () (*entity.MatchCase, error) {
|
|
err := this.ExpectValue(lexer.Symbol, "|")
|
|
if err != nil { return nil, err }
|
|
cas := &entity.MatchCase {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
this.Next()
|
|
cas.Declaration, err = this.parseDeclaration()
|
|
if err != nil { return nil, err }
|
|
cas.Expression, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
return cas, nil
|
|
}
|
|
|
|
func (this *treeParser) parseSwitch () (*entity.Switch, error) {
|
|
err := this.ExpectValue(lexer.Ident, "switch")
|
|
if err != nil { return nil, err }
|
|
switc := &entity.Switch {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
err = this.ExpectNextDesc(descriptionExpression, startTokensExpression...)
|
|
if err != nil { return nil, err }
|
|
switc.Value, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
for this.Is(lexer.Symbol) && this.ValueIs("|") {
|
|
cas, err := this.parseSwitchCase()
|
|
if err != nil { return nil, err }
|
|
switc.Cases = append(switc.Cases, cas)
|
|
}
|
|
|
|
if this.Is(lexer.Star) {
|
|
defaul, err := this.parseDefaultCase()
|
|
if err != nil { return nil, err }
|
|
switc.Default = defaul
|
|
}
|
|
|
|
return switc, nil
|
|
}
|
|
|
|
func (this *treeParser) parseSwitchCase () (*entity.SwitchCase, error) {
|
|
err := this.ExpectValue(lexer.Symbol, "|")
|
|
if err != nil { return nil, err }
|
|
cas := &entity.SwitchCase {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
this.Next()
|
|
cas.Key, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
cas.Expression, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
return cas, nil
|
|
}
|
|
|
|
func (this *treeParser) parseDefaultCase () (*entity.DefaultCase, error) {
|
|
err := this.Expect(lexer.Star)
|
|
if err != nil { return nil, err }
|
|
cas := &entity.DefaultCase {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
this.Next()
|
|
cas.Expression, err = this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
return cas, nil
|
|
}
|
|
|
|
func (this *treeParser) parseLoop () (*entity.Loop, error) {
|
|
err := this.ExpectValue(lexer.Ident, "loop")
|
|
if err != nil { return nil, err }
|
|
pos := this.Pos()
|
|
|
|
this.Next()
|
|
body, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
|
|
return &entity.Loop {
|
|
Pos: pos,
|
|
Body: body,
|
|
}, nil
|
|
}
|
|
|
|
func (this *treeParser) parseFor () (*entity.For, error) {
|
|
err := this.ExpectValue(lexer.Ident, "for")
|
|
if err != nil { return nil, err }
|
|
this.Next()
|
|
loop := &entity.For {
|
|
Pos: this.Pos(),
|
|
}
|
|
|
|
firstDeclaration, err := this.parseDeclaration()
|
|
if err != nil { return nil, err }
|
|
|
|
if this.ValueIs("in") {
|
|
loop.Element = firstDeclaration
|
|
} else {
|
|
loop.Index = firstDeclaration
|
|
element, err := this.parseDeclaration()
|
|
if err != nil { return nil, err }
|
|
loop.Element = element
|
|
}
|
|
|
|
err = this.ExpectValue(lexer.Ident, "in")
|
|
if err != nil { return nil, err }
|
|
this.Next()
|
|
|
|
over, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
loop.Over = over
|
|
|
|
body, err := this.parseExpression()
|
|
if err != nil { return nil, err }
|
|
loop.Body = body
|
|
|
|
return loop, nil
|
|
}
|