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) =
|
proc consume(parser: Parser, tokenType: TokenType | set[TokenType], msg: string) =
|
||||||
if not parser.match(tokenType):
|
if not parser.match(tokenType):
|
||||||
parser.errorAtCurrent(msg)
|
parser.errorAtCurrent(msg)
|
||||||
|
parser.advance() # stop infinite loops
|
||||||
|
|
||||||
proc peek(parser: Parser): Token =
|
proc peek(parser: Parser): Token =
|
||||||
parser.current
|
parser.current
|
||||||
|
@ -114,7 +115,7 @@ proc synchronize(parser: Parser) =
|
||||||
while parser.current.tokenType != tkEof:
|
while parser.current.tokenType != tkEof:
|
||||||
if parser.previous.get().tokenType in {tkSemicolon, tkRightBrace}:
|
if parser.previous.get().tokenType in {tkSemicolon, tkRightBrace}:
|
||||||
return
|
return
|
||||||
if parser.current.tokenType in {tkFunct, tkVar, tkFor, tkIf, tkWhile}:
|
if parser.current.tokenType in {tkProc, tkVar, tkFor, tkIf, tkWhile}:
|
||||||
return
|
return
|
||||||
parser.advance()
|
parser.advance()
|
||||||
|
|
||||||
|
@ -157,6 +158,24 @@ proc parseTable(parser: Parser): Node =
|
||||||
|
|
||||||
parser.consume(tkRightBrace, "'}' expected after table declaration.")
|
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 =
|
proc primary(parser: Parser): Node =
|
||||||
if parser.match(tkFalse):
|
if parser.match(tkFalse):
|
||||||
return Node(kind: nkConst, constant: ndFalse)
|
return Node(kind: nkConst, constant: ndFalse)
|
||||||
|
@ -182,6 +201,9 @@ proc primary(parser: Parser): Node =
|
||||||
result = parser.hold
|
result = parser.hold
|
||||||
parser.hold = nil
|
parser.hold = nil
|
||||||
return result
|
return result
|
||||||
|
if parser.match(tkProc):
|
||||||
|
parser.consume(tkLeftParen, "'(' expected after 'proc'.")
|
||||||
|
return parser.parseProcDeclaration()
|
||||||
|
|
||||||
parser.errorAtCurrent("Primary expected, but something else found.")
|
parser.errorAtCurrent("Primary expected, but something else found.")
|
||||||
|
|
||||||
|
@ -377,7 +399,6 @@ proc parseAssign(parser: Parser): Node =
|
||||||
# nkGetIndex
|
# nkGetIndex
|
||||||
result = Node(kind: nkSetIndex, sCollection: result.gCollection, sIndex: result.gIndex, sValue: right)
|
result = Node(kind: nkSetIndex, sCollection: result.gCollection, sIndex: result.gIndex, sValue: right)
|
||||||
|
|
||||||
|
|
||||||
proc parseAmpersand(parser: Parser): Node =
|
proc parseAmpersand(parser: Parser): Node =
|
||||||
result = parser.parseAssign()
|
result = parser.parseAssign()
|
||||||
if parser.match(tkAmpersand):
|
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 =
|
||||||
|
|
||||||
proc statement(parser: Parser): Node =
|
|
||||||
let expression = parser.expression()
|
let expression = parser.expression()
|
||||||
if expression != nil:
|
if expression != nil:
|
||||||
result = Node(kind: nkExprStmt, expression: expression)
|
result = Node(kind: nkExprStmt, expression: expression)
|
||||||
else:
|
else:
|
||||||
parser.errorAtCurrent("Expression expected.")
|
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:
|
if parser.panicMode:
|
||||||
parser.synchronize()
|
parser.synchronize()
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ type
|
||||||
tkStartList, tkStartTable, tkLeftBracket, tkRightBracket,
|
tkStartList, tkStartTable, tkLeftBracket, tkRightBracket,
|
||||||
tkHashtag, tkAmpersand,
|
tkHashtag, tkAmpersand,
|
||||||
tkIdentifier, tkString,
|
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,
|
tkOr, tkLabel, tkBreak, tkTrue, tkVar, tkWhile,
|
||||||
tkError, tkEof
|
tkError, tkEof
|
||||||
|
|
||||||
|
@ -142,11 +142,10 @@ proc scanNumber(scanner: Scanner): Token =
|
||||||
const keywords = {
|
const keywords = {
|
||||||
"and": tkAnd,
|
"and": tkAnd,
|
||||||
"break": tkBreak,
|
"break": tkBreak,
|
||||||
"def": tkDef,
|
|
||||||
"else": tkElse,
|
"else": tkElse,
|
||||||
"false": tkFalse,
|
"false": tkFalse,
|
||||||
"for": tkFor,
|
"for": tkFor,
|
||||||
"proc": tkFunct,
|
"proc": tkProc,
|
||||||
"goto": tkGoto,
|
"goto": tkGoto,
|
||||||
"if": tkIf,
|
"if": tkIf,
|
||||||
"nil": tkNil,
|
"nil": tkNil,
|
||||||
|
|
Loading…
Reference in New Issue