parsing procs
This commit is contained in:
parent
e83cd424f9
commit
a0e5431b0f
|
@ -102,6 +102,7 @@ proc match(parser: Parser, tokenTypes: set[TokenType]): bool =
|
|||
proc consume(parser: Parser, tokenType: TokenType | set[TokenType], msg: string) =
|
||||
if not parser.match(tokenType):
|
||||
parser.errorAtCurrent(msg)
|
||||
parser.advance() # stop infinite loops
|
||||
|
||||
proc peek(parser: Parser): Token =
|
||||
parser.current
|
||||
|
@ -114,7 +115,7 @@ proc synchronize(parser: Parser) =
|
|||
while parser.current.tokenType != tkEof:
|
||||
if parser.previous.get().tokenType in {tkSemicolon, tkRightBrace}:
|
||||
return
|
||||
if parser.current.tokenType in {tkFunct, tkVar, tkFor, tkIf, tkWhile}:
|
||||
if parser.current.tokenType in {tkProc, tkVar, tkFor, tkIf, tkWhile}:
|
||||
return
|
||||
parser.advance()
|
||||
|
||||
|
@ -157,6 +158,24 @@ proc parseTable(parser: Parser): Node =
|
|||
|
||||
parser.consume(tkRightBrace, "'}' expected after table declaration.")
|
||||
|
||||
proc parseProcDeclaration(parser: Parser): Node =
|
||||
# returns a nkProc, assumes that the left paren
|
||||
# has been consumed, so is followed by optionally
|
||||
# a param list, a ) and then an expression
|
||||
|
||||
var params: seq[string] = @[]
|
||||
|
||||
while not parser.isAtEnd() and not parser.peekMatch(tkRightParen):
|
||||
parser.consume(tkIdentifier, "Parameter name expected.")
|
||||
params.add(parser.previous.get().text)
|
||||
if not parser.isAtEnd() and not parser.peekMatch(tkRightParen):
|
||||
parser.consume(tkComma, "',' expected between parameters.")
|
||||
parser.consume(tkRightParen, "')' expected after parameter list.")
|
||||
|
||||
let body = parser.expression()
|
||||
|
||||
result = Node(kind: nkProc, parameters: params, procBody: body)
|
||||
|
||||
proc primary(parser: Parser): Node =
|
||||
if parser.match(tkFalse):
|
||||
return Node(kind: nkConst, constant: ndFalse)
|
||||
|
@ -182,6 +201,9 @@ proc primary(parser: Parser): Node =
|
|||
result = parser.hold
|
||||
parser.hold = nil
|
||||
return result
|
||||
if parser.match(tkProc):
|
||||
parser.consume(tkLeftParen, "'(' expected after 'proc'.")
|
||||
return parser.parseProcDeclaration()
|
||||
|
||||
parser.errorAtCurrent("Primary expected, but something else found.")
|
||||
|
||||
|
@ -377,7 +399,6 @@ proc parseAssign(parser: Parser): Node =
|
|||
# nkGetIndex
|
||||
result = Node(kind: nkSetIndex, sCollection: result.gCollection, sIndex: result.gIndex, sValue: right)
|
||||
|
||||
|
||||
proc parseAmpersand(parser: Parser): Node =
|
||||
result = parser.parseAssign()
|
||||
if parser.match(tkAmpersand):
|
||||
|
@ -392,15 +413,34 @@ proc expression(parser: Parser): Node =
|
|||
|
||||
proc statement(parser: Parser): Node
|
||||
|
||||
|
||||
|
||||
proc statement(parser: Parser): Node =
|
||||
proc exprStatement(parser: Parser): Node =
|
||||
let expression = parser.expression()
|
||||
if expression != nil:
|
||||
result = Node(kind: nkExprStmt, expression: expression)
|
||||
else:
|
||||
parser.errorAtCurrent("Expression expected.")
|
||||
parser.consume(tkSemicolon, "; expected after expression statement.")
|
||||
parser.consume(tkSemicolon, "';' expected after expression statement.")
|
||||
|
||||
proc statement(parser: Parser): Node =
|
||||
if parser.match(tkProc):
|
||||
# it is possibly a proc declaration, but
|
||||
# it could also be a proc expression
|
||||
|
||||
if parser.peekMatch(tkLeftParen):
|
||||
# proc expression - backtrack and let it go to expression statement
|
||||
parser.backtrack()
|
||||
result = parser.exprStatement()
|
||||
else:
|
||||
# proc definition - var declaration sort of code
|
||||
parser.consume(tkIdentifier, "Procedure name expected after 'proc'.")
|
||||
let varname = parser.previous.get().text
|
||||
parser.consume(tkLeftParen, "'(' expected after procedure name.")
|
||||
let funct = parser.parseProcDeclaration()
|
||||
result = Node(kind: nkVarDecl, name: varname, value: funct)
|
||||
parser.consume(tkSemicolon, "';' expected after procedure declaration.")
|
||||
else:
|
||||
result = parser.exprStatement()
|
||||
|
||||
if parser.panicMode:
|
||||
parser.synchronize()
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ type
|
|||
tkStartList, tkStartTable, tkLeftBracket, tkRightBracket,
|
||||
tkHashtag, tkAmpersand,
|
||||
tkIdentifier, tkString,
|
||||
tkNumber, tkAnd, tkDef, tkElse, tkFalse, tkFor, tkFunct, tkGoto, tkIf, tkNil,
|
||||
tkNumber, tkAnd, tkElse, tkFalse, tkFor, tkProc, tkGoto, tkIf, tkNil,
|
||||
tkOr, tkLabel, tkBreak, tkTrue, tkVar, tkWhile,
|
||||
tkError, tkEof
|
||||
|
||||
|
@ -142,11 +142,10 @@ proc scanNumber(scanner: Scanner): Token =
|
|||
const keywords = {
|
||||
"and": tkAnd,
|
||||
"break": tkBreak,
|
||||
"def": tkDef,
|
||||
"else": tkElse,
|
||||
"false": tkFalse,
|
||||
"for": tkFor,
|
||||
"proc": tkFunct,
|
||||
"proc": tkProc,
|
||||
"goto": tkGoto,
|
||||
"if": tkIf,
|
||||
"nil": tkNil,
|
||||
|
|
Loading…
Reference in New Issue