|
@@ -31,8 +31,11 @@ BLOCK -> openblock STATEMENTS closeblock .
|
|
|
LIST -> openlist PARAMETERS closelist .
|
|
|
VALUE -> string | int | float | symbol | type .
|
|
|
WORDVALUE -> word | VALUE.
|
|
|
-SETTER -> set word PARAMETER .
|
|
|
-GETTER -> get word .
|
|
|
+SETTER -> set TARGET .
|
|
|
+TARGET -> word PARAMETER | GETTER PARAMETER .
|
|
|
+GETTER -> get ORIGIN .
|
|
|
+ORIGIN -> word | SETTER | GETTER .
|
|
|
+
|
|
|
|
|
|
*
|
|
|
* program -> statements
|
|
@@ -78,11 +81,33 @@ func (parser *Parser) Advance() {
|
|
|
parser.LogDebug("Next token: %s\n", token.String())
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+the token kinds given in kinds. In this case it will return the accepted
|
|
|
+token and advance the parser. Otherwise, it will call panicf with ann
|
|
|
+* "Suntax error unexpected <token>".*/
|
|
|
+func (parser *Parser) Require(kinds ...TokenKind) Token {
|
|
|
+ if parser.current.IsNone() {
|
|
|
+ parser.Advance()
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, kind := range kinds {
|
|
|
+ if kind == parser.current.TokenKind {
|
|
|
+ accepted := parser.current
|
|
|
+ parser.Advance()
|
|
|
+ parser.LogDebug("Require: Accepted token: %s\n", accepted.String())
|
|
|
+ return accepted
|
|
|
+ }
|
|
|
+ }
|
|
|
+ parser.Panicf("error: unexpected token %s", parser.current.String())
|
|
|
+ return Token{}
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
the token kinds given in kinds. In this case it will return the accepted
|
|
|
token and advance the parser. Otherwise, if no token kind matches, the lexer
|
|
|
does not advance and the current token remains the same, except if that was nil.*/
|
|
|
-func (parser *Parser) Accept(kinds ...TokenKind) Token {
|
|
|
+func (parser *Parser) AcceptDeprecated(kinds ...TokenKind) Token {
|
|
|
if parser.current.IsNone() {
|
|
|
parser.Advance()
|
|
|
}
|
|
@@ -123,6 +148,7 @@ func (parser *Parser) ParseMany(kind AstKind, parent *Ast, parsefunc func(*Parse
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (parser *Parser) NewAstError(message string, args ...interface{}) *Ast {
|
|
|
sv := StringValue(fmt.Sprintf(message+" at token "+parser.current.String(), args))
|
|
|
pos := parser.current.Position
|
|
@@ -130,7 +156,7 @@ func (parser *Parser) NewAstError(message string, args ...interface{}) *Ast {
|
|
|
return NewAst(AstKindError, nil, EmptyAstArray(), tok)
|
|
|
}
|
|
|
|
|
|
-func (parser *Parser) ParseAny(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
|
|
|
+func (parser *Parser) ParseAnyDeprecated(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
|
|
|
var ast * Ast
|
|
|
if astkind != AstKindFlatten {
|
|
|
ast = NewEmptyAst(astkind)
|
|
@@ -152,8 +178,8 @@ func (parser *Parser) ParseAny(astkind AstKind, parsefuncs ...(func(*Parser) *As
|
|
|
return NewAstNone()
|
|
|
}
|
|
|
|
|
|
-func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
|
|
|
- ast := parser.ParseAny(astkind, parsefuncs...)
|
|
|
+func (parser *Parser) ParseRequireAnyDeprecated(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
|
|
|
+ ast := parser.ParseAnyDeprecated(astkind, parsefuncs...)
|
|
|
if ast.IsNone() {
|
|
|
err := parser.NewAstError("Unexpected token in %v", parsefuncs)
|
|
|
return err
|
|
@@ -176,16 +202,16 @@ func (parser *Parser) NewAst(kind AstKind, parent * Ast, children []*Ast, value
|
|
|
func (parser *Parser) ParseValue() *Ast {
|
|
|
parser.LogDebug("ParseValue: %s\n", parser.current.String())
|
|
|
|
|
|
- value := parser.Accept(TokenKindInteger, TokenKindString,
|
|
|
- TokenKindBoolean, TokenKindNil, TokenKindFloat, TokenKindSymbol)
|
|
|
+ value := parser.Require(TokenKindInteger, TokenKindString,
|
|
|
+ TokenKindBoolean, TokenKindNil, TokenKindNil, TokenKindFloat, TokenKindSymbol)
|
|
|
return parser.NewAst(AstKindValue, nil, EmptyAstArray(), value)
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseWordValue() *Ast {
|
|
|
parser.LogDebug("ParseWordValue: %s\n", parser.current.String())
|
|
|
|
|
|
- value := parser.Accept(TokenKindInteger, TokenKindString,
|
|
|
- TokenKindBoolean, TokenKindNil, TokenKindFloat, TokenKindSymbol,
|
|
|
+ value := parser.Require(TokenKindInteger, TokenKindString,
|
|
|
+ TokenKindBoolean, TokenKindNil, TokenKindNil, TokenKindFloat, TokenKindSymbol,
|
|
|
TokenKindType, TokenKindWord)
|
|
|
return parser.NewAst(AstKindWordValue, nil, EmptyAstArray(), value)
|
|
|
}
|
|
@@ -193,26 +219,34 @@ func (parser *Parser) ParseWordValue() *Ast {
|
|
|
func (parser *Parser) ParseArgument() *Ast {
|
|
|
parser.LogDebug("ParseArgument: %s\n", parser.current.String())
|
|
|
|
|
|
- return parser.ParseAny(AstKindArgument,
|
|
|
- (*Parser).ParseGet,
|
|
|
- (*Parser).ParseSet,
|
|
|
- (*Parser).ParseClosed,
|
|
|
- (*Parser).ParseWordValue)
|
|
|
+ switch {
|
|
|
+ case parser.NextIsGet(): return parser.ParseGet()
|
|
|
+ case parser.NextIsSet(): return parser.ParseSet()
|
|
|
+ case parser.NextIsClosed(): return parser.ParseClosed()
|
|
|
+ case parser.NextIsWordValue(): return parser.ParseWordValue()
|
|
|
+ default: parser.Panicf("error: in argument: unexpected %s", parser.current.String())
|
|
|
+ return nil
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseArguments() *Ast {
|
|
|
- parser.LogDebug("ParseArgument: %s\n", parser.current.String())
|
|
|
- return parser.ParseMany(AstKindArguments, nil, (*Parser).ParseArgument)
|
|
|
+ parser.LogDebug("ParseArguments: %s\n", parser.current.String())
|
|
|
+
|
|
|
+ ast := NewAstWithToken(AstKindArguments, parser.current)
|
|
|
+ var children []*Ast
|
|
|
+ for parser.NextIsArgument() {
|
|
|
+ child := parser.ParseArgument()
|
|
|
+ children = append(children, child)
|
|
|
+ }
|
|
|
+ ast.AppendChildren(children...)
|
|
|
+ return ast
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseList() *Ast {
|
|
|
parser.LogDebug("ParseList: %s\n", parser.current.String())
|
|
|
|
|
|
- op := parser.Accept(TokenKindOpenList)
|
|
|
- if op.IsNone() {
|
|
|
- return NewAstNone()
|
|
|
- }
|
|
|
- if op.IsError() {
|
|
|
+ op := parser.Require(TokenKindOpenList)
|
|
|
+ if op.IsError() {
|
|
|
return parser.NewAstError("Unexpected value.")
|
|
|
}
|
|
|
|
|
@@ -221,7 +255,7 @@ func (parser *Parser) ParseList() *Ast {
|
|
|
if AstIsError(args) {
|
|
|
return args
|
|
|
}
|
|
|
- if cp := parser.Accept(TokenKindCloseList); cp.IsNone() || cp.IsError() {
|
|
|
+ if cp := parser.Require(TokenKindCloseList); cp.IsError() {
|
|
|
return parser.NewAstError("expected closing brackets")
|
|
|
}
|
|
|
|
|
@@ -232,11 +266,7 @@ func (parser *Parser) ParseList() *Ast {
|
|
|
func (parser *Parser) ParseParenthesis() *Ast {
|
|
|
parser.LogDebug("ParseParenthesis: %s\n", parser.current.String())
|
|
|
|
|
|
- op := parser.Accept(TokenKindOpenParen)
|
|
|
-
|
|
|
- if op.IsNone() {
|
|
|
- return NewAstNone()
|
|
|
- }
|
|
|
+ op := parser.Require(TokenKindOpenParen)
|
|
|
if op.IsError() {
|
|
|
return parser.NewAstError("Unexpected value.")
|
|
|
}
|
|
@@ -250,7 +280,7 @@ func (parser *Parser) ParseParenthesis() *Ast {
|
|
|
if AstIsError(expr) {
|
|
|
return expr
|
|
|
}
|
|
|
- if cp := parser.Accept(TokenKindCloseParen); cp.IsNone() || cp.IsError() {
|
|
|
+ if cp := parser.Require(TokenKindCloseParen); cp.IsError() {
|
|
|
return parser.NewAstError("expected closing parenthesis")
|
|
|
}
|
|
|
|
|
@@ -261,10 +291,7 @@ func (parser *Parser) ParseParenthesis() *Ast {
|
|
|
func (parser *Parser) ParseBlock() *Ast {
|
|
|
parser.LogDebug("ParseBlock: %s\n", parser.current.String())
|
|
|
|
|
|
- op := parser.Accept(TokenKindOpenBlock)
|
|
|
- if op.IsNone() {
|
|
|
- return NewAstNone()
|
|
|
- }
|
|
|
+ op := parser.Require(TokenKindOpenBlock)
|
|
|
if op.IsError() {
|
|
|
return parser.NewAstError("Unexpected value.")
|
|
|
}
|
|
@@ -277,7 +304,7 @@ func (parser *Parser) ParseBlock() *Ast {
|
|
|
if AstIsError(stats) {
|
|
|
return stats
|
|
|
}
|
|
|
- if cp := parser.Accept(TokenKindCloseBlock); cp.IsNone() || cp.IsError() {
|
|
|
+ if cp := parser.Require(TokenKindCloseBlock); cp.IsError() {
|
|
|
return parser.NewAstError("expected closing block")
|
|
|
}
|
|
|
|
|
@@ -285,53 +312,81 @@ func (parser *Parser) ParseBlock() *Ast {
|
|
|
return ast
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
func (parser *Parser) ParseTarget() *Ast {
|
|
|
parser.LogDebug("ParseTarget: %s\n", parser.current.String())
|
|
|
-
|
|
|
- target := parser.Accept(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
- ast := NewAstWithToken(AstKindTarget, target)
|
|
|
-
|
|
|
- if target.IsNone() {
|
|
|
- paren := parser.ParseParenthesis()
|
|
|
- if paren.IsNone() {
|
|
|
- return parser.NewAstError("expected word, symbol or parenthesis")
|
|
|
- }
|
|
|
- ast.AppendChild(paren)
|
|
|
+ var target *Ast
|
|
|
+
|
|
|
+ switch {
|
|
|
+ case parser.NextIs(TokenKindWord, TokenKindType, TokenKindSymbol):
|
|
|
+
|
|
|
+ token := parser.Require(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
+ target = NewAstWithToken(AstKindTarget, token)
|
|
|
+ case parser.NextIsGet():
|
|
|
+
|
|
|
+ target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
+ target.AppendChild(parser.ParseGet())
|
|
|
+ case parser.NextIsClosed():
|
|
|
+
|
|
|
+ target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
+ target.AppendChild(parser.ParseClosed())
|
|
|
+ default:
|
|
|
+ parser.Panicf("Malformed setter: %s", parser.current.String())
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ argument := parser.ParseArgument()
|
|
|
+ if argument.IsNone() {
|
|
|
+ return parser.NewAstError("Expected argument to set")
|
|
|
}
|
|
|
+ target.AppendChild(argument)
|
|
|
|
|
|
- return ast
|
|
|
+ return target
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+func (parser *Parser) ParseOrigin() *Ast {
|
|
|
+ parser.LogDebug("ParseOrigin: %s\n", parser.current.String())
|
|
|
+ var target *Ast
|
|
|
+
|
|
|
+ switch {
|
|
|
+ case parser.NextIs(TokenKindWord, TokenKindType, TokenKindSymbol):
|
|
|
+
|
|
|
+ token := parser.Require(TokenKindWord, TokenKindType, TokenKindSymbol)
|
|
|
+ target = NewAstWithToken(AstKindTarget, token)
|
|
|
+ case parser.NextIsGet():
|
|
|
+
|
|
|
+ target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
+ target.AppendChild(parser.ParseGet())
|
|
|
+ case parser.NextIsClosed():
|
|
|
+
|
|
|
+ target = NewAstWithToken(AstKindTarget, parser.current)
|
|
|
+ target.AppendChild(parser.ParseClosed())
|
|
|
+ default:
|
|
|
+ parser.Panicf("Malformed getter: %s", parser.current.String())
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return target
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
func (parser *Parser) ParseSet() *Ast {
|
|
|
parser.LogDebug("ParseSet: %s\n", parser.current.String())
|
|
|
|
|
|
- set := parser.Accept(TokenKindSet)
|
|
|
- if set.IsNone() {
|
|
|
- return NewAstNone()
|
|
|
- }
|
|
|
-
|
|
|
+ set := parser.Require(TokenKindSet)
|
|
|
ast := NewAstWithToken(AstKindSet, set)
|
|
|
target := parser.ParseTarget()
|
|
|
ast.AppendChild(target)
|
|
|
-
|
|
|
- argument := parser.ParseArgument()
|
|
|
- if argument.IsNone() {
|
|
|
- return parser.NewAstError("Expected argument to set")
|
|
|
- }
|
|
|
- ast.AppendChild(argument)
|
|
|
return ast
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseGet() *Ast {
|
|
|
parser.LogDebug("ParseGet: %s\n", parser.current.String())
|
|
|
|
|
|
- get := parser.Accept(TokenKindGet)
|
|
|
- if get.IsNone() {
|
|
|
- return NewAstNone()
|
|
|
- }
|
|
|
+ get := parser.Require(TokenKindGet)
|
|
|
ast := NewAstWithToken(AstKindGet, get)
|
|
|
- target := parser.ParseTarget()
|
|
|
+ target := parser.ParseOrigin()
|
|
|
ast.AppendChild(target)
|
|
|
return ast
|
|
|
}
|
|
@@ -339,10 +394,7 @@ func (parser *Parser) ParseGet() *Ast {
|
|
|
func (parser *Parser) ParseCommand() *Ast {
|
|
|
parser.LogDebug("ParseCommand: %s\n", parser.current.String())
|
|
|
|
|
|
- word := parser.Accept(TokenKindWord, TokenKindType)
|
|
|
- if word.IsNone() {
|
|
|
- return NewAstNone()
|
|
|
- }
|
|
|
+ word := parser.Require(TokenKindWord, TokenKindType)
|
|
|
arguments := parser.ParseArguments()
|
|
|
command := NewAstWithToken(AstKindCommand, word)
|
|
|
command.AppendChild(arguments)
|
|
@@ -351,17 +403,28 @@ func (parser *Parser) ParseCommand() *Ast {
|
|
|
|
|
|
func (parser *Parser) ParseClosed() *Ast {
|
|
|
parser.LogDebug("ParseClosed: %s\n", parser.current.String())
|
|
|
- exp := parser.ParseAny(AstKindClosed, (*Parser).ParseParenthesis,
|
|
|
- (*Parser).ParseBlock, (*Parser).ParseList)
|
|
|
- return exp
|
|
|
+ switch {
|
|
|
+ case parser.NextIs(TokenKindOpenBlock): return parser.ParseBlock()
|
|
|
+ case parser.NextIs(TokenKindOpenParen): return parser.ParseParenthesis()
|
|
|
+ case parser.NextIs(TokenKindOpenList): return parser.ParseList()
|
|
|
+ default:
|
|
|
+ parser.Panicf("Syntax error in closed, unexpected: %s", parser.current.String())
|
|
|
+ return nil
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseExpression() *Ast {
|
|
|
parser.LogDebug("ParseExpression: %s\n", parser.current.String())
|
|
|
- exp := parser.ParseRequireAny(AstKindExpression, (*Parser).ParseCommand,
|
|
|
- (*Parser).ParseSet,
|
|
|
- (*Parser).ParseGet, (*Parser).ParseValue )
|
|
|
- return exp
|
|
|
+
|
|
|
+ switch {
|
|
|
+ case parser.NextIsWord(): return parser.ParseCommand()
|
|
|
+ case parser.NextIsSet(): return parser.ParseSet()
|
|
|
+ case parser.NextIsGet(): return parser.ParseGet()
|
|
|
+ case parser.NextIsValue(): return parser.ParseValue()
|
|
|
+ default:
|
|
|
+ parser.Panicf("Syntax error in expression, unexpected: %s", parser.current.String())
|
|
|
+ return nil
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseExpressionStatement() *Ast {
|
|
@@ -371,21 +434,21 @@ func (parser *Parser) ParseExpressionStatement() *Ast {
|
|
|
return NewAstNone()
|
|
|
}
|
|
|
|
|
|
- if eox := parser.Accept(TokenKindEOX); eox.IsNone() {
|
|
|
+
|
|
|
+ if eox := parser.Require(TokenKindEOX); eox.IsError() {
|
|
|
return parser.NewAstError("expected end of statement")
|
|
|
}
|
|
|
|
|
|
- return NewAstNone()
|
|
|
+ return expr
|
|
|
}
|
|
|
|
|
|
|
|
|
func (parser *Parser) ParseEmptyStatement() *Ast {
|
|
|
parser.LogDebug("ParseEmptyStatement: %s\n", parser.current.String())
|
|
|
- if eox := parser.Accept(TokenKindEOX); eox.IsNone() {
|
|
|
+ if eox := parser.Require(TokenKindEOX); eox.IsError() {
|
|
|
return parser.NewAstError("expected end of statement")
|
|
|
}
|
|
|
return NewAstWithToken(AstKindStatement, parser.current)
|
|
|
-
|
|
|
}
|
|
|
|
|
|
func (parser Parser) NextIs(kinds ...TokenKind) bool {
|
|
@@ -408,20 +471,34 @@ func (parser Parser) NextIsWord() bool {
|
|
|
return parser.NextIs(TokenKindWord)
|
|
|
}
|
|
|
|
|
|
-func (parser Parser) NextIsGetter() bool {
|
|
|
+func (parser Parser) NextIsGet() bool {
|
|
|
return parser.NextIs(TokenKindGet)
|
|
|
}
|
|
|
|
|
|
-func (parser Parser) NextIsSetter() bool {
|
|
|
+func (parser Parser) NextIsSet() bool {
|
|
|
return parser.NextIs(TokenKindSet)
|
|
|
}
|
|
|
|
|
|
func (parser Parser) NextIsValue() bool {
|
|
|
return parser.NextIs(TokenKindString, TokenKindType,
|
|
|
- TokenKindInteger, TokenKindFloat, TokenKindBoolean,
|
|
|
+ TokenKindInteger, TokenKindFloat, TokenKindBoolean, TokenKindNil,
|
|
|
TokenKindSymbol)
|
|
|
}
|
|
|
|
|
|
+func (parser Parser) NextIsWordValue() bool {
|
|
|
+ return parser.NextIs(TokenKindWord, TokenKindString, TokenKindType,
|
|
|
+ TokenKindInteger, TokenKindFloat, TokenKindBoolean, TokenKindNil,
|
|
|
+ TokenKindSymbol)
|
|
|
+}
|
|
|
+
|
|
|
+func (parser Parser) NextIsArgument() bool {
|
|
|
+ return parser.NextIs(TokenKindOpenBlock, TokenKindOpenList, TokenKindOpenParen,
|
|
|
+ TokenKindSet, TokenKindGet, TokenKindWord, TokenKindString, TokenKindType,
|
|
|
+ TokenKindInteger, TokenKindFloat, TokenKindBoolean, TokenKindNil,
|
|
|
+ TokenKindSymbol)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
func (parser Parser) NextIsEOX() bool {
|
|
|
return parser.NextIs(TokenKindEOX)
|
|
|
}
|
|
@@ -439,10 +516,14 @@ func (parser Parser) NextIsExpression() bool {
|
|
|
TokenKindType,
|
|
|
TokenKindInteger,
|
|
|
TokenKindFloat,
|
|
|
- TokenKindBoolean,
|
|
|
+ TokenKindBoolean, TokenKindNil,
|
|
|
TokenKindSymbol)
|
|
|
}
|
|
|
|
|
|
+func (parser Parser) NextIsStatement() bool {
|
|
|
+ return parser.NextIsExpression() || parser.NextIsClosed() || parser.NextIsEOX()
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
func (parser *Parser) ParseStatement() *Ast {
|
|
|
parser.LogDebug("ParseStatement: %s\n", parser.current.String())
|
|
@@ -450,7 +531,6 @@ func (parser *Parser) ParseStatement() *Ast {
|
|
|
case parser.NextIsClosed(): return parser.ParseClosed()
|
|
|
case parser.NextIsExpression(): return parser.ParseExpressionStatement()
|
|
|
case parser.NextIsEOX(): return parser.ParseEmptyStatement()
|
|
|
- case parser.NextIsEOF(): return NewAstNone()
|
|
|
default:
|
|
|
parser.Panicf("Unexpected token in statement")
|
|
|
return parser.NewAstError("Unexpected token in statement")
|
|
@@ -459,18 +539,27 @@ func (parser *Parser) ParseStatement() *Ast {
|
|
|
|
|
|
func (parser *Parser) ParseStatements() *Ast {
|
|
|
parser.LogDebug("ParseStatements: %s\n", parser.current.String())
|
|
|
- return parser.ParseMany(AstKindStatements, nil, (*Parser).ParseStatement)
|
|
|
+
|
|
|
+ ast := NewAstWithToken(AstKindStatements, parser.current)
|
|
|
+ var children []*Ast
|
|
|
+ for parser.NextIsStatement() {
|
|
|
+ child := parser.ParseStatement()
|
|
|
+ children = append(children, child)
|
|
|
+ }
|
|
|
+ ast.AppendChildren(children...)
|
|
|
+ return ast
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
func (parser *Parser) ParseProgram() *Ast {
|
|
|
parser.LogDebug("ParseProgram: %s\n", parser.current.String())
|
|
|
|
|
|
- stats := parser.ParseStatements()
|
|
|
-
|
|
|
- eof := parser.Accept(TokenKindEOF)
|
|
|
+ stats := parser.ParseStatements()
|
|
|
+ eof := parser.Require(TokenKindEOF)
|
|
|
aeof := NewAstWithToken(AstKindEnd, eof)
|
|
|
if eof.IsNone() {
|
|
|
- aeof = parser.NewAstError("Expceted EOF, have: %s", parser.current.String())
|
|
|
+ aeof = parser.NewAstError("Expected EOF, have: %s", parser.current.String())
|
|
|
}
|
|
|
children := []*Ast{stats, aeof}
|
|
|
return NewAst(AstKindProgram, nil, children, NoToken())
|
|
@@ -478,9 +567,11 @@ func (parser *Parser) ParseProgram() *Ast {
|
|
|
|
|
|
func (parser *Parser) Parse() *Ast {
|
|
|
defer func() {
|
|
|
- err := recover()
|
|
|
- fmt.Printf("Parse error: %s\n", err)
|
|
|
+ if err := recover() ; err != nil {
|
|
|
+ fmt.Printf("Parse error, recovered: %s %s\n", err, parser.current.String())
|
|
|
+ }
|
|
|
} ()
|
|
|
+ parser.Advance()
|
|
|
ast := parser.ParseProgram()
|
|
|
return ast
|
|
|
}
|