diff options
Diffstat (limited to 'compiler/parser.nim')
-rw-r--r-- | compiler/parser.nim | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 69e372e4e..54b360a24 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -37,8 +37,7 @@ type TParser* = object # A TParser object represents a file that # is being parsed currInd: int # current indentation level - firstTok, strongSpaces: bool # Has the first token been read? - # Is strongSpaces on? + firstTok: bool # Has the first token been read? hasProgress: bool # some while loop requires progress ensurance lex*: TLexer # The lexer that is used for parsing tok*: TToken # The current token @@ -46,7 +45,7 @@ type inSemiStmtList*: int emptyNode: PNode when defined(nimpretty2): - em: Emitter + em*: Emitter SymbolMode = enum smNormal, smAllowNil, smAfterDot @@ -102,8 +101,7 @@ proc getTok(p: var TParser) = emitTok(p.em, p.lex, p.tok) proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream, - cache: IdentCache; config: ConfigRef; - strongSpaces=false) = + cache: IdentCache; config: ConfigRef) = ## Open a parser, using the given arguments to set up its internal state. ## initToken(p.tok) @@ -112,13 +110,11 @@ proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream, openEmitter(p.em, cache, config, fileIdx) getTok(p) # read the first token p.firstTok = true - p.strongSpaces = strongSpaces p.emptyNode = newNode(nkEmpty) proc openParser*(p: var TParser, filename: AbsoluteFile, inputStream: PLLStream, - cache: IdentCache; config: ConfigRef; - strongSpaces=false) = - openParser(p, fileInfoIdx(config, filename), inputStream, cache, config, strongSpaces) + cache: IdentCache; config: ConfigRef) = + openParser(p, fileInfoIdx(config, filename), inputStream, cache, config) proc closeParser(p: var TParser) = ## Close a parser, freeing up its resources. @@ -286,7 +282,7 @@ proc checkBinary(p: TParser) {.inline.} = #| #| prefixOperator = operator #| -#| optInd = COMMENT? +#| optInd = COMMENT? IND? #| optPar = (IND{>} | IND{=})? #| #| simpleExpr = arrowExpr (OP0 optInd arrowExpr)* pragma? @@ -602,7 +598,7 @@ proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode = #| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')' #| arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']' case p.tok.tokType - of tkSymbol, tkBuiltInMagics: + of tkSymbol, tkBuiltInMagics, tkOut: result = newIdentNodeP(p.tok.ident, p) getTok(p) result = parseGStrLit(p, result) @@ -706,8 +702,11 @@ proc namedParams(p: var TParser, callee: PNode, # progress guaranteed exprColonEqExprListAux(p, endTok, result) -proc commandParam(p: var TParser, isFirstParam: var bool): PNode = - result = parseExpr(p) +proc commandParam(p: var TParser, isFirstParam: var bool; mode: TPrimaryMode): PNode = + if mode == pmTypeDesc: + result = simpleExpr(p, mode) + else: + result = parseExpr(p) if p.tok.tokType == tkDo: result = postExprBlocks(p, result) elif p.tok.tokType == tkEquals and not isFirstParam: @@ -780,7 +779,7 @@ proc primarySuffix(p: var TParser, r: PNode, when true: # progress NOT guaranteed p.hasProgress = false - addSon result, commandParam(p, isFirstParam) + addSon result, commandParam(p, isFirstParam, mode) if not p.hasProgress: break else: while p.tok.tokType != tkEof: @@ -798,7 +797,7 @@ proc parseOperators(p: var TParser, headNode: PNode, limit: int, mode: TPrimaryMode): PNode = result = headNode # expand while operators have priorities higher than 'limit' - var opPrec = getPrecedence(p.tok, p.strongSpaces) + var opPrec = getPrecedence(p.tok, false) let modeB = if mode == pmTypeDef: pmTypeDesc else: mode # the operator itself must not start on a new line: # progress guaranteed @@ -815,7 +814,7 @@ proc parseOperators(p: var TParser, headNode: PNode, addSon(a, result) addSon(a, b) result = a - opPrec = getPrecedence(p.tok, p.strongSpaces) + opPrec = getPrecedence(p.tok, false) proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode = result = primary(p, mode) @@ -1037,6 +1036,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode = addSon(result, p.emptyNode) # return type when defined(nimpretty2): inc p.em.doIndentMore + inc p.em.keepIndents let hasParLe = p.tok.tokType == tkParLe and p.tok.indent < 0 if hasParLe: getTok(p) @@ -1073,6 +1073,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode = result = p.emptyNode when defined(nimpretty2): dec p.em.doIndentMore + dec p.em.keepIndents proc optPragmas(p: var TParser): PNode = if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)): @@ -1244,7 +1245,6 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode = optInd(p, result) addSon(result, primary(p, pmNormal)) of tkVar: result = parseTypeDescKAux(p, nkVarTy, mode) - of tkOut: result = parseTypeDescKAux(p, nkVarTy, mode) of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode) of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode) of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, mode) @@ -1254,14 +1254,29 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode = if mode != pmSkipSuffix: result = primarySuffix(p, result, baseInd, mode) +proc binaryNot(p: var TParser; a: PNode): PNode = + if p.tok.tokType == tkNot: + let notOpr = newIdentNodeP(p.tok.ident, p) + getTok(p) + optInd(p, notOpr) + let b = parseExpr(p) + result = newNodeP(nkInfix, p) + result.add notOpr + result.add a + result.add b + else: + result = a + proc parseTypeDesc(p: var TParser): PNode = - #| typeDesc = simpleExpr + #| typeDesc = simpleExpr ('not' expr)? result = simpleExpr(p, pmTypeDesc) + result = binaryNot(p, result) proc parseTypeDefAux(p: var TParser): PNode = - #| typeDefAux = simpleExpr + #| typeDefAux = simpleExpr ('not' expr)? #| | 'concept' typeClass result = simpleExpr(p, pmTypeDef) + result = binaryNot(p, result) proc makeCall(n: PNode): PNode = ## Creates a call if the given node isn't already a call. @@ -1369,12 +1384,12 @@ proc parseExprStmt(p: var TParser): PNode = while true: getTok(p) optInd(p, result) - addSon(result, commandParam(p, isFirstParam)) + addSon(result, commandParam(p, isFirstParam, pmNormal)) if p.tok.tokType != tkComma: break elif p.tok.indent < 0 and isExprStart(p): result = newNode(nkCommand, a.info, @[a]) while true: - addSon(result, commandParam(p, isFirstParam)) + addSon(result, commandParam(p, isFirstParam, pmNormal)) if p.tok.tokType != tkComma: break getTok(p) optInd(p, result) @@ -1578,7 +1593,6 @@ proc parseTry(p: var TParser; isExpr: bool): PNode = colcom(p, b) addSon(b, parseStmt(p)) addSon(result, b) - if b.kind == nkFinally: break if b == nil: parMessage(p, "expected 'except'") proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode = @@ -2236,10 +2250,8 @@ proc parseString*(s: string; cache: IdentCache; config: ConfigRef; stream.lineOffset = line var parser: TParser - # XXX for now the builtin 'parseStmt/Expr' functions do not know about strong - # spaces... parser.lex.errorHandler = errorHandler - openParser(parser, AbsoluteFile filename, stream, cache, config, false) + openParser(parser, AbsoluteFile filename, stream, cache, config) result = parser.parseAll closeParser(parser) |