diff --git a/src/build/ast/Parse.go b/src/build/ast/Parse.go index aa4eeef..eaaad01 100644 --- a/src/build/ast/Parse.go +++ b/src/build/ast/Parse.go @@ -27,45 +27,38 @@ func Parse(tokens token.List) (AST, error) { // toASTNode generates an AST node from an instruction. func toASTNode(tokens token.List) (Node, error) { if tokens[0].Kind == token.Keyword { - switch tokens[0].Text() { - case keyword.Return: + word := tokens[0].Text() + + if word == keyword.Return { value := expression.Parse(tokens[1:]) return &Return{Value: value}, nil - - case keyword.Loop: - blockStart := tokens.IndexKind(token.BlockStart) - blockEnd := tokens.LastIndexKind(token.BlockEnd) - - if blockStart == -1 { - return nil, errors.New(errors.MissingBlockStart, nil, tokens[0].End()) - } - - if blockEnd == -1 { - return nil, errors.New(errors.MissingBlockEnd, nil, tokens[len(tokens)-1].End()) - } - - body, err := Parse(tokens[blockStart+1 : blockEnd]) - return &Loop{Body: body}, err - - case keyword.If: - blockStart := tokens.IndexKind(token.BlockStart) - blockEnd := tokens.LastIndexKind(token.BlockEnd) - - if blockStart == -1 { - return nil, errors.New(errors.MissingBlockStart, nil, tokens[0].End()) - } - - if blockEnd == -1 { - return nil, errors.New(errors.MissingBlockEnd, nil, tokens[len(tokens)-1].End()) - } - - condition := expression.Parse(tokens[1:blockStart]) - body, err := Parse(tokens[blockStart+1 : blockEnd]) - return &If{Condition: condition, Body: body}, err - - default: - return nil, errors.New(&errors.KeywordNotImplemented{Keyword: tokens[0].Text()}, nil, tokens[0].Position) } + + if keywordHasBlock(word) { + blockStart := tokens.IndexKind(token.BlockStart) + blockEnd := tokens.LastIndexKind(token.BlockEnd) + + if blockStart == -1 { + return nil, errors.New(errors.MissingBlockStart, nil, tokens[0].End()) + } + + if blockEnd == -1 { + return nil, errors.New(errors.MissingBlockEnd, nil, tokens[len(tokens)-1].End()) + } + + body, err := Parse(tokens[blockStart+1 : blockEnd]) + + switch word { + case keyword.If: + condition := expression.Parse(tokens[1:blockStart]) + return &If{Condition: condition, Body: body}, err + + case keyword.Loop: + return &Loop{Body: body}, err + } + } + + return nil, errors.New(&errors.KeywordNotImplemented{Keyword: word}, nil, tokens[0].Position) } expr := expression.Parse(tokens) @@ -115,3 +108,8 @@ func IsFunctionCall(expr *expression.Expression) bool { func IsVariableDefinition(expr *expression.Expression) bool { return expr.Token.Kind == token.Operator && expr.Token.Text() == ":=" } + +// keywordHasBlock returns true if the keyword requires a block. +func keywordHasBlock(word string) bool { + return word == keyword.If || word == keyword.Loop +}