From 3afbe24b7c7d458e3d65bf96328262d941600fe8 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sat, 24 May 2014 23:28:13 -0400 Subject: Document parser structures and procedures. --- compiler/parser.nim | 59 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 20 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 5c7b86240..2f9deb6b3 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -28,25 +28,20 @@ import llstream, lexer, idents, strutils, ast, astalgo, msgs type - TParser*{.final.} = object # a TParser object represents a module that + TParser*{.final.} = object # A TParser object represents a module that # is being parsed - currInd: int # current indentation - firstTok, strongSpaces: bool - lex*: TLexer # the lexer that is used for parsing - tok*: TToken # the current token - inPragma: int + currInd: int # current indentation level + firstTok, strongSpaces: bool # Has the first token been read? + # Is strongSpaces on? + lex*: TLexer # The lexer that is used for parsing + tok*: TToken # The current token + inPragma: int # Pragma level inSemiStmtList: int proc parseAll*(p: var TParser): PNode proc closeParser*(p: var TParser) proc parseTopLevelStmt*(p: var TParser): PNode - # implements an iterator. Returns the next top-level statement or - # emtyNode if end of stream. - proc parseString*(s: string, filename: string = "", line: int = 0): PNode - # filename and line could be set optionally, when the string originates - # from a certain source file. This way, the compiler could generate - # correct error messages referring to the original source. # helpers for the other parsers proc isOperator*(tok: TToken): bool @@ -72,11 +67,15 @@ proc parseTry(p: var TParser): PNode proc parseCase(p: var TParser): PNode # implementation -proc getTok(p: var TParser) = +proc getTok(p: var TParser) = + ## Get the next token from the parser's lexer, and store it in the parser's + ## `tok` member. rawGetTok(p.lex, p.tok) proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream, strongSpaces=false) = + ## Open a parser, using the given arguments to set up its internal state. + ## initToken(p.tok) openLexer(p.lex, fileIdx, inputStream) getTok(p) # read the first token @@ -87,13 +86,16 @@ proc openParser*(p: var TParser, filename: string, inputStream: PLLStream, strongSpaces=false) = openParser(p, filename.fileInfoIdx, inputstream, strongSpaces) -proc closeParser(p: var TParser) = +proc closeParser(p: var TParser) = + ## Close a parser, freeing up its resources. closeLexer(p.lex) -proc parMessage(p: TParser, msg: TMsgKind, arg: string = "") = +proc parMessage(p: TParser, msg: TMsgKind, arg = "") = + ## Produce and emit the parser message `arg` to output. lexMessage(p.lex, msg, arg) -proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) = +proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) = + ## Produce and emit a parser message to output about the token `tok` lexMessage(p.lex, msg, prettyTok(tok)) template withInd(p: expr, body: stmt) {.immediate.} = @@ -143,10 +145,13 @@ proc expectIdent(p: TParser) = lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok)) proc eat(p: var TParser, tokType: TTokType) = + ## Move the parser to the next token if the current token is of type + ## `tokType`, otherwise error. if p.tok.tokType == tokType: getTok(p) else: lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType]) proc parLineInfo(p: TParser): TLineInfo = + ## Retrieve the line information associated with the parser's current state. result = getLineInfo(p.lex, p.tok) proc indAndComment(p: var TParser, n: PNode) = @@ -192,9 +197,11 @@ proc isSigilLike(tok: TToken): bool {.inline.} = result = tok.tokType == tkOpr and relevantOprChar(tok.ident) == '@' proc isLeftAssociative(tok: TToken): bool {.inline.} = + ## Determines whether the token is left assocative. result = tok.tokType != tkOpr or relevantOprChar(tok.ident) != '^' proc getPrecedence(tok: TToken, strongSpaces: bool): int = + ## Calculates the precedence of the given token. template considerStrongSpaces(x): expr = x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0) @@ -224,22 +231,26 @@ proc getPrecedence(tok: TToken, strongSpaces: bool): int = else: result = -10 proc isOperator(tok: TToken): bool = + ## Determines if the given token is an operator type token. tok.tokType in {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor} proc isUnary(p: TParser): bool = + ## Check if the current parser token is a unary operator p.strongSpaces and p.tok.tokType in {tkOpr, tkDotDot} and p.tok.strongSpaceB == 0 and p.tok.strongSpaceA > 0 proc checkBinary(p: TParser) {.inline.} = + ## Check if the current parser token is a binary operator. # we don't check '..' here as that's too annoying if p.strongSpaces and p.tok.tokType == tkOpr: if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB: - parMessage(p, errGenerated, "number of spaces around '$#' not consistent"% - prettyTok(p.tok)) + parMessage(p, errGenerated, + "Number of spaces around '$#' not consistent" % + prettyTok(p.tok)) elif p.tok.strongSpaceA notin {0,1,2,4,8}: - parMessage(p, errGenerated, "number of spaces must be 0,1,2,4 or 8") + parMessage(p, errGenerated, "Number of spaces must be 0,1,2,4 or 8") #| module = stmt ^* (';' / IND{=}) #| @@ -1108,6 +1119,7 @@ proc parseTypeDefAux(p: var TParser): PNode = result = simpleExpr(p, pmTypeDef) proc makeCall(n: PNode): PNode = + ## Creates a call if the given node isn't already a call. if n.kind in nkCallKinds: result = n else: @@ -1952,7 +1964,8 @@ proc parseStmt(p: var TParser): PNode = if p.tok.tokType != tkSemiColon: break getTok(p) -proc parseAll(p: var TParser): PNode = +proc parseAll(p: var TParser): PNode = + ## Parses the rest of the input stream held by the parser into a PNode. result = newNodeP(nkStmtList, p) while p.tok.tokType != tkEof: var a = complexOrSimpleStmt(p) @@ -1966,6 +1979,8 @@ proc parseAll(p: var TParser): PNode = parMessage(p, errInvalidIndentation) proc parseTopLevelStmt(p: var TParser): PNode = + ## Implements an iterator which, when called repeatedly, returns the next + ## top-level statement or emptyNode if end of stream. result = ast.emptyNode while true: if p.tok.indent != 0: @@ -1984,6 +1999,10 @@ proc parseTopLevelStmt(p: var TParser): PNode = break proc parseString(s: string, filename: string = "", line: int = 0): PNode = + ## Parses a string into an AST, returning the top node. + ## `filename` and `line`, although optional, provide info so that the + ## compiler can generate correct error messages referring to the original + ## source. var stream = llStreamOpen(s) stream.lineOffset = line -- cgit 1.4.1-2-gfad0 From 3db3c0e3827a9a9bd70a8f635b0e6650c89b2b7b Mon Sep 17 00:00:00 2001 From: flaviut Date: Tue, 3 Jun 2014 10:12:31 -0400 Subject: Generalize accent parsing --- compiler/parser.nim | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 2f9deb6b3..61816f443 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -147,8 +147,10 @@ proc expectIdent(p: TParser) = proc eat(p: var TParser, tokType: TTokType) = ## Move the parser to the next token if the current token is of type ## `tokType`, otherwise error. - if p.tok.tokType == tokType: getTok(p) - else: lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType]) + if p.tok.tokType == tokType: + getTok(p) + else: + lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType]) proc parLineInfo(p: TParser): TLineInfo = ## Retrieve the line information associated with the parser's current state. @@ -285,7 +287,7 @@ proc colcom(p: var TParser, n: PNode) = skipComment(p, n) proc parseSymbol(p: var TParser, allowNil = false): PNode = - #| symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`' + #| symbol = '`' (KEYW|IDENT|operator|'('|')'|'['|']'|'{'|'}'|'='|literal)+ '`' #| | IDENT case p.tok.tokType of tkSymbol: @@ -296,29 +298,16 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = getTok(p) while true: case p.tok.tokType - of tkBracketLe: - add(result, newIdentNodeP(getIdent"[]", p)) - getTok(p) - eat(p, tkBracketRi) - of tkEquals: - add(result, newIdentNodeP(getIdent"=", p)) - getTok(p) - of tkParLe: - add(result, newIdentNodeP(getIdent"()", p)) - getTok(p) - eat(p, tkParRi) - of tkCurlyLe: - add(result, newIdentNodeP(getIdent"{}", p)) + of tkIntLit..tkCharLit, tkBracketLe, tkBracketRi, tkParLe, tkParRi, + tkCurlyRi, tkCurlyLe, tkEquals: + add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p)) getTok(p) - eat(p, tkCurlyRi) of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDot, tkDotDot: add(result, newIdentNodeP(p.tok.ident, p)) getTok(p) - of tkIntLit..tkCharLit: - add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p)) - getTok(p) else: if result.len == 0: + echo repr p.tok parMessage(p, errIdentifierExpected, p.tok) break eat(p, tkAccent) -- cgit 1.4.1-2-gfad0 From 20cb567bf5e404a30bb4b898b87865e4304b1130 Mon Sep 17 00:00:00 2001 From: flaviut Date: Tue, 3 Jun 2014 10:22:12 -0400 Subject: Fix accents in enums --- compiler/parser.nim | 8 +++++--- compiler/semtypes.nim | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 61816f443..f89aee119 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -296,20 +296,22 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = of tkAccent: result = newNodeP(nkAccQuoted, p) getTok(p) + var bracketAccm = "" while true: case p.tok.tokType of tkIntLit..tkCharLit, tkBracketLe, tkBracketRi, tkParLe, tkParRi, tkCurlyRi, tkCurlyLe, tkEquals: - add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p)) + bracketAccm.add(tokToStr(p.tok)) getTok(p) of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDot, tkDotDot: add(result, newIdentNodeP(p.tok.ident, p)) getTok(p) else: - if result.len == 0: - echo repr p.tok + if result.len == 0 and bracketAccm == "": parMessage(p, errIdentifierExpected, p.tok) break + if bracketAccm != "": + result.add(newIdentNodeP(getIdent(bracketAccm), p)) eat(p, tkAccent) else: if allowNil and p.tok.tokType == tkNil: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index d70ed3465..2dcca8f1e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -70,9 +70,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = counter = x of nkSym: e = n.sons[i].sym - of nkIdent: + of nkIdent, nkAccQuoted: e = newSymS(skEnumField, n.sons[i], c) - else: illFormedAst(n[i]) + else: + illFormedAst(n[i]) e.typ = result e.position = int(counter) if e.position == 0: hasNull = true -- cgit 1.4.1-2-gfad0 From 7a9bcf47697a004de8d3b3ec54beb8ac4bdb9872 Mon Sep 17 00:00:00 2001 From: flaviut Date: Tue, 3 Jun 2014 18:58:59 -0400 Subject: Clean up code --- compiler/parser.nim | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index f89aee119..ae115e749 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -296,22 +296,17 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = of tkAccent: result = newNodeP(nkAccQuoted, p) getTok(p) - var bracketAccm = "" + var accm = "" while true: case p.tok.tokType - of tkIntLit..tkCharLit, tkBracketLe, tkBracketRi, tkParLe, tkParRi, - tkCurlyRi, tkCurlyLe, tkEquals: - bracketAccm.add(tokToStr(p.tok)) - getTok(p) - of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDot, tkDotDot: - add(result, newIdentNodeP(p.tok.ident, p)) - getTok(p) - else: - if result.len == 0 and bracketAccm == "": + of tkAccent, tkEof: + if accm == "": parMessage(p, errIdentifierExpected, p.tok) break - if bracketAccm != "": - result.add(newIdentNodeP(getIdent(bracketAccm), p)) + else: + accm.add(tokToStr(p.tok)) + getTok(p) + result.add(newIdentNodeP(getIdent(accm), p)) eat(p, tkAccent) else: if allowNil and p.tok.tokType == tkNil: -- cgit 1.4.1-2-gfad0 From 90dc35c10998c279daf2b413aaf896cadaced699 Mon Sep 17 00:00:00 2001 From: flaviut Date: Wed, 4 Jun 2014 15:30:37 -0400 Subject: fix bug with unexpected tkInvalid,tkEof,tkComment --- compiler/parser.nim | 2 ++ 1 file changed, 2 insertions(+) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index ae115e749..ec829f644 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -303,6 +303,8 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = if accm == "": parMessage(p, errIdentifierExpected, p.tok) break + of tkEof, tkInvalid, tkComment: + parMessage(p, errIdentifierExpected, p.tok) else: accm.add(tokToStr(p.tok)) getTok(p) -- cgit 1.4.1-2-gfad0 From 6b9359d90161887b2dc4fa12d9861883d22530f6 Mon Sep 17 00:00:00 2001 From: flaviut Date: Wed, 4 Jun 2014 15:40:31 -0400 Subject: updated grammer, fixed oversight --- compiler/parser.nim | 2 +- doc/grammar.txt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index ec829f644..7b6ef8ee5 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -299,7 +299,7 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = var accm = "" while true: case p.tok.tokType - of tkAccent, tkEof: + of tkAccent: if accm == "": parMessage(p, errIdentifierExpected, p.tok) break diff --git a/doc/grammar.txt b/doc/grammar.txt index 63e898e11..61557b68c 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -24,7 +24,7 @@ ampExpr = plusExpr (OP6 optInd plusExpr)* plusExpr = mulExpr (OP7 optInd mulExpr)* mulExpr = dollarExpr (OP8 optInd dollarExpr)* dollarExpr = primary (OP9 optInd primary)* -symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`' +symbol = '`' (KEYW|IDENT|operator|'('|')'|'['|']'|'{'|'}'|'='|literal)+ '`' | IDENT indexExpr = expr indexExprList = indexExpr ^+ comma @@ -166,7 +166,6 @@ object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart typeClassParam = ('var')? symbol typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')? &IND{>} stmt -distinct = 'distinct' optInd typeDesc typeDef = identWithPragma genericParamList? '=' optInd typeDefAux indAndComment? varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr -- cgit 1.4.1-2-gfad0 From 145cb3ae8ccf58495a3e38f6646041661de2affb Mon Sep 17 00:00:00 2001 From: flaviut Date: Sun, 8 Jun 2014 15:46:19 -0400 Subject: fix overlooked grammer comment --- compiler/parser.nim | 1 + doc/grammar.txt | 1 + 2 files changed, 2 insertions(+) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 7b6ef8ee5..0f52750c9 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -981,6 +981,7 @@ proc parseSymbolList(p: var TParser, result: PNode, allowNil = false) = proc parseTypeDescKAux(p: var TParser, kind: TNodeKind, mode: TPrimaryMode): PNode = + #| distinct = 'distinct' optInd typeDesc result = newNodeP(kind, p) getTok(p) optInd(p, result) diff --git a/doc/grammar.txt b/doc/grammar.txt index 61557b68c..fe5341840 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -82,6 +82,7 @@ paramListColon = paramList? (':' optInd typeDesc)? doBlock = 'do' paramListArrow pragmas? colcom stmt doBlocks = doBlock ^* IND{=} procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)? +distinct = 'distinct' optInd typeDesc expr = (ifExpr | whenExpr | caseExpr -- cgit 1.4.1-2-gfad0 From ce29b9f78c74285a31908135a73ee62051bd7525 Mon Sep 17 00:00:00 2001 From: flaviut Date: Sun, 8 Jun 2014 19:41:36 -0400 Subject: fix tokenizing bug --- compiler/parser.nim | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 0f52750c9..18de1570a 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -287,7 +287,7 @@ proc colcom(p: var TParser, n: PNode) = skipComment(p, n) proc parseSymbol(p: var TParser, allowNil = false): PNode = - #| symbol = '`' (KEYW|IDENT|operator|'('|')'|'['|']'|'{'|'}'|'='|literal)+ '`' + #| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`' #| | IDENT case p.tok.tokType of tkSymbol: @@ -296,19 +296,24 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = of tkAccent: result = newNodeP(nkAccQuoted, p) getTok(p) - var accm = "" while true: case p.tok.tokType of tkAccent: - if accm == "": + if result.len == 0: parMessage(p, errIdentifierExpected, p.tok) break - of tkEof, tkInvalid, tkComment: - parMessage(p, errIdentifierExpected, p.tok) - else: - accm.add(tokToStr(p.tok)) + of tkOpr, tkDot, tkDotDot, tkEquals, tkParLe..tkParDotRi: + var accm = "" + while p.tok.tokType in {tkOpr, tkDot, tkDotDot, tkEquals, + tkParLe..tkParDotRi}: + accm.add(tokToStr(p.tok)) + getTok(p) + result.add(newIdentNodeP(getIdent(accm), p)) + of tokKeywordLow..tokKeywordHigh, tkSymbol, tkIntLit..tkCharLit: + result.add(newIdentNodeP(getIdent(tokToStr(p.tok)), p)) getTok(p) - result.add(newIdentNodeP(getIdent(accm), p)) + else: + parMessage(p, errIdentifierExpected, p.tok) eat(p, tkAccent) else: if allowNil and p.tok.tokType == tkNil: -- cgit 1.4.1-2-gfad0 From 212293197fe9e3584f8c36142935ce6d6f5b30c3 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 1 Jul 2014 21:47:53 +0200 Subject: fixes #1161 --- compiler/parser.nim | 21 ++++++++++++--------- doc/grammar.txt | 5 ++++- tests/exprs/tstmtexprs.nim | 32 +++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 11 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 18de1570a..6ff0c2dfc 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -63,7 +63,7 @@ proc optInd*(p: var TParser, n: PNode) proc indAndComment*(p: var TParser, n: PNode) proc setBaseFlags*(n: PNode, base: TNumericalBase) proc parseSymbol*(p: var TParser, allowNil = false): PNode -proc parseTry(p: var TParser): PNode +proc parseTry(p: var TParser; isExpr: bool): PNode proc parseCase(p: var TParser): PNode # implementation @@ -845,7 +845,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode = addSon(result, parseTypeDesc(p)) else: addSon(result, ast.emptyNode) - if (p.tok.tokType != tkEquals) and not (withBothOptional in flags): + if p.tok.tokType != tkEquals and withBothOptional notin flags: parMessage(p, errColonOrEqualsExpected, p.tok) if p.tok.tokType == tkEquals: getTok(p) @@ -1004,13 +1004,13 @@ proc parseExpr(p: var TParser): PNode = #| expr = (ifExpr #| | whenExpr #| | caseExpr - #| | tryStmt) + #| | tryExpr) #| / simpleExpr case p.tok.tokType: of tkIf: result = parseIfExpr(p, nkIfExpr) of tkWhen: result = parseIfExpr(p, nkWhenExpr) of tkCase: result = parseCase(p) - of tkTry: result = parseTry(p) + of tkTry: result = parseTry(p, isExpr=true) else: result = simpleExpr(p) proc parseEnum(p: var TParser): PNode @@ -1363,22 +1363,25 @@ proc parseCase(p: var TParser): PNode = if wasIndented: p.currInd = oldInd -proc parseTry(p: var TParser): PNode = +proc parseTry(p: var TParser; isExpr: bool): PNode = #| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally') #| (IND{=}? 'except' exprList colcom stmt)* #| (IND{=}? 'finally' colcom stmt)? + #| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally') + #| (optInd 'except' exprList colcom stmt)* + #| (optInd 'finally' colcom stmt)? result = newNodeP(nkTryStmt, p) getTok(p) eat(p, tkColon) skipComment(p, result) addSon(result, parseStmt(p)) var b: PNode = nil - while sameOrNoInd(p): + while sameOrNoInd(p) or isExpr: case p.tok.tokType - of tkExcept: + of tkExcept: b = newNodeP(nkExceptBranch, p) exprList(p, tkColon, b) - of tkFinally: + of tkFinally: b = newNodeP(nkFinally, p) getTokNoInd(p) eat(p, tkColon) @@ -1877,7 +1880,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode = of tkIf: result = parseIfOrWhen(p, nkIfStmt) of tkWhile: result = parseWhile(p) of tkCase: result = parseCase(p) - of tkTry: result = parseTry(p) + of tkTry: result = parseTry(p, isExpr=false) of tkFinally: result = parseExceptBlock(p, nkFinally) of tkExcept: result = parseExceptBlock(p, nkExceptBranch) of tkFor: result = parseFor(p) diff --git a/doc/grammar.txt b/doc/grammar.txt index 47ae095f6..a54428678 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -86,7 +86,7 @@ distinct = 'distinct' optInd typeDesc expr = (ifExpr | whenExpr | caseExpr - | tryStmt) + | tryExpr) / simpleExpr typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'type' | 'tuple' | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum' @@ -135,6 +135,9 @@ caseStmt = 'case' expr ':'? COMMENT? tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally') (IND{=}? 'except' exprList colcom stmt)* (IND{=}? 'finally' colcom stmt)? +tryExpr = 'try' colcom stmt &(optInd 'except'|'finally') + (optInd 'except' exprList colcom stmt)* + (optInd 'finally' colcom stmt)? exceptBlock = 'except' colcom stmt forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt blockStmt = 'block' symbol? colcom stmt diff --git a/tests/exprs/tstmtexprs.nim b/tests/exprs/tstmtexprs.nim index ed0066287..d6b827b6d 100644 --- a/tests/exprs/tstmtexprs.nim +++ b/tests/exprs/tstmtexprs.nim @@ -4,7 +4,8 @@ discard """ 1244 6 abcdefghijklmnopqrstuvwxyz -145 23''' +145 23 +3''' """ import strutils @@ -92,3 +93,32 @@ proc parseResponse(): PJsonNode = #bug #992 var se = @[1,2] let b = (se[1] = 1; 1) + + +# bug #1161 + +type + PFooBase = ref object of PObject + field: int + + PFoo[T] = ref object of PFooBase + field2: T + +var testIf = + if true: + 2 + else: + 3 + +var testCase = + case 8 + of 8: 9 + else: 10 + +var testTry = + try: + PFoo[string](field: 3, field2: "asfasf") + except: + PFooBase(field: 5) + +echo(testTry.field) -- cgit 1.4.1-2-gfad0