From a0e5431b0f61492c48e5e95b186031c0198cd7db Mon Sep 17 00:00:00 2001 From: prod2 <95874442+prod2@users.noreply.github.com> Date: Fri, 2 Dec 2022 21:08:52 +0100 Subject: [PATCH] parsing procs --- src/ndspkg/compv2/parser.nim | 52 +++++++++++++++++++++++++++++++----- src/ndspkg/scanner.nim | 5 ++-- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/ndspkg/compv2/parser.nim b/src/ndspkg/compv2/parser.nim index de17448..23d8563 100644 --- a/src/ndspkg/compv2/parser.nim +++ b/src/ndspkg/compv2/parser.nim @@ -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() diff --git a/src/ndspkg/scanner.nim b/src/ndspkg/scanner.nim index a3f62e3..def2c9c 100644 --- a/src/ndspkg/scanner.nim +++ b/src/ndspkg/scanner.nim @@ -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,