diff options
Diffstat (limited to 'compiler/parser.nim')
-rw-r--r-- | compiler/parser.nim | 163 |
1 files changed, 81 insertions, 82 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index fabe4bcc8..e2d17b455 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -67,6 +67,8 @@ proc parseTry(p: var TParser; isExpr: bool): PNode proc parseCase(p: var TParser): PNode proc parseStmtPragma(p: var TParser): PNode proc parsePragma(p: var TParser): PNode +proc postExprBlocks(p: var TParser, x: PNode): PNode +proc parseExprStmt(p: var TParser): PNode # implementation proc getTok(p: var TParser) = @@ -194,7 +196,6 @@ proc newIdentNodeP(ident: PIdent, p: TParser): PNode = proc parseExpr(p: var TParser): PNode proc parseStmt(p: var TParser): PNode proc parseTypeDesc(p: var TParser): PNode -proc parseDoBlocks(p: var TParser, call: PNode) proc parseParamList(p: var TParser, retColon = true): PNode proc isSigilLike(tok: TToken): bool {.inline.} = @@ -365,7 +366,10 @@ proc colonOrEquals(p: var TParser, a: PNode): PNode = proc exprColonEqExpr(p: var TParser): PNode = #| exprColonEqExpr = expr (':'|'=' expr)? var a = parseExpr(p) - result = colonOrEquals(p, a) + if p.tok.tokType == tkDo: + result = postExprBlocks(p, a) + else: + result = colonOrEquals(p, a) proc exprList(p: var TParser, endTok: TTokType, result: PNode) = #| exprList = expr ^+ comma @@ -520,7 +524,9 @@ proc parsePar(p: var TParser): PNode = result.add(parseStmtPragma(p)) elif p.tok.tokType != tkParRi: var a = simpleExpr(p) - if p.tok.tokType == tkEquals: + if p.tok.tokType == tkDo: + result = postExprBlocks(p, a) + elif p.tok.tokType == tkEquals: # special case: allow assignments let asgn = newNodeP(nkAsgn, p) getTok(p) @@ -669,7 +675,6 @@ proc namedParams(p: var TParser, callee: PNode, # progress guaranteed exprColonEqExprListAux(p, endTok, result) -proc parseMacroColon(p: var TParser, x: PNode): PNode proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode = #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks? #| | doBlocks @@ -696,14 +701,6 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode = result = namedParams(p, result, nkCall, tkParRi) if result.len > 1 and result.sons[1].kind == nkExprColonExpr: result.kind = nkObjConstr - elif p.tok.tokType == tkDo: - parseDoBlocks(p, result) - of tkDo: - # progress guaranteed - var a = result - result = newNodeP(nkCall, p) - addSon(result, a) - parseDoBlocks(p, result) of tkDot: # progress guaranteed result = dotExpr(p, result) @@ -735,10 +732,7 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, x) - if p.tok.tokType == tkDo: - parseDoBlocks(p, result) - else: - result = parseMacroColon(p, result) + result = postExprBlocks(p, result) break else: break @@ -977,16 +971,9 @@ proc parseDoBlock(p: var TParser; info: TLineInfo): PNode = let params = parseParamList(p, retColon=false) let pragmas = optPragmas(p) colcom(p, result) - result = newProcNode(nkDo, info, parseStmt(p), - params = params, - pragmas = pragmas) - -proc parseDoBlocks(p: var TParser, call: PNode) = - #| doBlocks = doBlock ^* IND{=} - while sameOrNoInd(p) and p.tok.tokType == tkDo: - let info = parLineInfo(p) - getTok(p) - addSon(call, parseDoBlock(p, info)) + result = parseStmt(p) + if params.kind != nkEmpty: + result = newProcNode(nkDo, info, result, params = params, pragmas = pragmas) proc parseProcExpr(p: var TParser, isExpr: bool): PNode = #| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)? @@ -1162,49 +1149,75 @@ proc makeCall(n: PNode): PNode = result = newNodeI(nkCall, n.info) result.add n -proc parseMacroColon(p: var TParser, x: PNode): PNode = - #| macroColon = ':' stmt? ( IND{=} 'of' exprList ':' stmt - #| | IND{=} 'elif' expr ':' stmt - #| | IND{=} 'except' exprList ':' stmt - #| | IND{=} 'else' ':' stmt )* +proc postExprBlocks(p: var TParser, x: PNode): PNode = + #| postExprBlocks = ':' stmt? ( IND{=} doBlock + #| | IND{=} 'of' exprList ':' stmt + #| | IND{=} 'elif' expr ':' stmt + #| | IND{=} 'except' exprList ':' stmt + #| | IND{=} 'else' ':' stmt )* result = x - if p.tok.tokType == tkColon and p.tok.indent < 0: + if p.tok.indent >= 0: return + + var + openingParams = emptyNode + openingPragmas = emptyNode + + if p.tok.tokType == tkDo: + getTok(p) + openingParams = parseParamList(p, retColon=false) + openingPragmas = optPragmas(p) + + if p.tok.tokType == tkColon: result = makeCall(result) getTok(p) skipComment(p, result) - let stmtList = newNodeP(nkStmtList, p) if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}: - let body = parseStmt(p) - stmtList.add body - #addSon(result, makeStmtList(body)) - # progress guaranteed + var stmtList = newNodeP(nkStmtList, p) + stmtList.add parseStmt(p) + # to keep backwards compatibility (see tests/vm/tstringnil) + if stmtList[0].kind == nkStmtList: stmtList = stmtList[0] + + stmtList.flags.incl nfBlockArg + if openingParams.kind != nkEmpty: + result.add newProcNode(nkDo, stmtList.info, stmtList, + params = openingParams, pragmas = openingPragmas) + else: + result.add stmtList + while sameInd(p): - var b: PNode - case p.tok.tokType - of tkOf: - b = newNodeP(nkOfBranch, p) - exprList(p, tkColon, b) - of tkElif: - b = newNodeP(nkElifBranch, p) - getTok(p) - optInd(p, b) - addSon(b, parseExpr(p)) - of tkExcept: - b = newNodeP(nkExceptBranch, p) - exprList(p, tkColon, b) - of tkElse: - b = newNodeP(nkElse, p) + var nextBlock: PNode + let nextToken = p.tok.tokType + if nextToken == tkDo: + let info = parLineInfo(p) getTok(p) - else: break - eat(p, tkColon) - addSon(b, parseStmt(p)) - addSon(stmtList, b) - if b.kind == nkElse: break - if stmtList.len == 1 and stmtList[0].kind == nkStmtList: - # to keep backwards compatibility (see tests/vm/tstringnil) - result.add stmtList[0] - else: - result.add stmtList + nextBlock = parseDoBlock(p, info) + else: + case nextToken: + of tkOf: + nextBlock = newNodeP(nkOfBranch, p) + exprList(p, tkColon, nextBlock) + of tkElif: + nextBlock = newNodeP(nkElifBranch, p) + getTok(p) + optInd(p, nextBlock) + nextBlock.addSon parseExpr(p) + of tkExcept: + nextBlock = newNodeP(nkExceptBranch, p) + exprList(p, tkColon, nextBlock) + of tkElse: + nextBlock = newNodeP(nkElse, p) + getTok(p) + else: break + eat(p, tkColon) + nextBlock.addSon parseStmt(p) + + nextBlock.flags.incl nfBlockArg + result.add nextBlock + + if nextBlock.kind == nkElse: break + else: + if openingParams.kind != nkEmpty: + parMessage(p, errTokenExpected, ":") proc parseExprStmt(p: var TParser): PNode = #| exprStmt = simpleExpr @@ -1219,12 +1232,7 @@ proc parseExprStmt(p: var TParser): PNode = getTok(p) optInd(p, result) var b = parseExpr(p) - if p.tok.tokType == tkColon and p.tok.indent < 0: - if b.kind != nkEmpty: - let call = makeCall(b) - call.add parseDoBlock(p, parLineInfo(p)) - parseDoBlocks(p, call) - b = call + b = postExprBlocks(p, b) addSon(result, a) addSon(result, b) else: @@ -1247,11 +1255,7 @@ proc parseExprStmt(p: var TParser): PNode = optInd(p, result) else: result = a - if p.tok.tokType == tkDo and p.tok.indent < 0: - result = makeCall(result) - parseDoBlocks(p, result) - return result - result = parseMacroColon(p, result) + result = postExprBlocks(p, result) proc parseModuleName(p: var TParser, kind: TNodeKind): PNode = result = parseExpr(p) @@ -1341,7 +1345,9 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode = # NL terminates: addSon(result, ast.emptyNode) else: - addSon(result, parseExpr(p)) + var e = parseExpr(p) + e = postExprBlocks(p, e) + addSon(result, e) proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode = #| condStmt = expr colcom stmt COMMENT? @@ -1893,14 +1899,7 @@ proc parseVariable(p: var TParser): PNode = #| variable = (varTuple / identColonEquals) colonBody? indAndComment if p.tok.tokType == tkParLe: result = parseVarTuple(p) else: result = parseIdentColonEquals(p, {withPragma}) - if p.tok.tokType == tkColon and p.tok.indent < 0: - let last = result.len-1 - let ex = result.sons[last] - if ex.kind != nkEmpty: - let call = makeCall(ex) - call.add parseDoBlock(p, parLineInfo(p)) - parseDoBlocks(p, call) - result.sons[last] = call + result{-1} = postExprBlocks(p, result{-1}) indAndComment(p, result) proc parseBind(p: var TParser, k: TNodeKind): PNode = |