From f15b4ccb520b541b1bbaf2c0ae042b98bc8360cc Mon Sep 17 00:00:00 2001 From: ReneSac Date: Thu, 9 Apr 2015 17:00:11 -0300 Subject: Restrict arrow-like operators to start with - or = --- compiler/parser.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index f135c540c..f195892eb 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -212,7 +212,8 @@ proc getPrecedence(tok: TToken, strongSpaces: bool): int = let relevantChar = tok.ident.s[0] # arrow like? - if L > 1 and tok.ident.s[L-1] == '>': return considerStrongSpaces(1) + if L > 1 and tok.ident.s[L-1] == '>' and tok.ident.s[0] in {'-', '='}: + return considerStrongSpaces(1) template considerAsgn(value: expr) = result = if tok.ident.s[L-1] == '=': 1 else: value -- cgit 1.4.1-2-gfad0 From 34997292f48d40e8ed49d84c999b6d32afa3b044 Mon Sep 17 00:00:00 2001 From: ReneSac Date: Fri, 10 Apr 2015 23:59:17 -0300 Subject: Changing the rule for arrow like operators again. --- compiler/parser.nim | 2 +- doc/manual/syntax.txt | 4 ++-- tests/parser/tstrongspaces.nim | 10 +++++----- web/news.txt | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index f195892eb..2d363638f 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -212,7 +212,7 @@ proc getPrecedence(tok: TToken, strongSpaces: bool): int = let relevantChar = tok.ident.s[0] # arrow like? - if L > 1 and tok.ident.s[L-1] == '>' and tok.ident.s[0] in {'-', '='}: + if L > 1 and tok.ident.s[^1] == '>' and tok.ident.s[^2] in {'-', '~', '='}: return considerStrongSpaces(1) template considerAsgn(value: expr) = diff --git a/doc/manual/syntax.txt b/doc/manual/syntax.txt index 0f2208d30..f6fe0652d 100644 --- a/doc/manual/syntax.txt +++ b/doc/manual/syntax.txt @@ -15,8 +15,8 @@ Associativity Binary operators whose first character is ``^`` are right-associative, all other binary operators are left-associative. -Operators whose the first character is either ``-`` or ``=`` and the last -character is ``>`` are called `arrow like`:idx:. +Operators ending in either ``->``, ``~>`` or ``=>`` are called +`arrow like`:idx:. Precedence diff --git a/tests/parser/tstrongspaces.nim b/tests/parser/tstrongspaces.nim index eaf4d908c..e70b91988 100644 --- a/tests/parser/tstrongspaces.nim +++ b/tests/parser/tstrongspaces.nim @@ -73,11 +73,11 @@ echo "all" | tester & " " & args echo "all"|tester & " " & args # Test arrow like operators. See also tests/macros/tclosuremacro.nim -proc `-+>`(a, b: int): int = a + b*4 +proc `+->`(a, b: int): int = a + b*4 template `===>`(a, b: int): expr = a - b shr 1 -echo 3 -+> 2 + 2 and 4 -var arrowed = 3-+>2 + 2 and 4 # arrowed = 4 +echo 3 +-> 2 + 2 and 4 +var arrowed = 3+->2 + 2 and 4 # arrowed = 4 echo arrowed ===> 15 -echo (2 * 3-+>2) == (2*3 -+> 2) -echo arrowed ===> 2 + 3-+>2 +echo (2 * 3+->2) == (2*3 +-> 2) +echo arrowed ===> 2 + 3+->2 diff --git a/web/news.txt b/web/news.txt index c515e2ec2..b5b897c1a 100644 --- a/web/news.txt +++ b/web/news.txt @@ -34,10 +34,10 @@ News should be used instead. - ``nim idetools`` has been replaced by a separate tool `nimsuggest`_. - *arrow like* operators are not right associative anymore. - - *arrow like* operators are now required to start with ``=`` or ``-`` in - addition to end with ``>``. Examples of arrow like operators that continue - to work are: ``->``, ``==>``, ``=+>``. On the other hand, the following - operators are now considered regular operators: ``|>``, ``+->``, etc. + - *arrow like* operators are now required end with either ``->``, ``~>`` or + ``=>``, not just ``>``. Examples of operators still considered arrow like: + ``->``, ``==>``, ``+=>``. On the other hand, the following operators are now + considered regular operators again: ``|>``, ``-+>``, etc. - Typeless parameters are now only allowed in templates and macros. The old way turned out to be too error-prone. - The 'addr' and 'type' operators are now parsed as unary function -- cgit 1.4.1-2-gfad0 From 06617bbb76d4b9ecc0c40072ca472c4b3428514a Mon Sep 17 00:00:00 2001 From: ReneSac Date: Sat, 11 Apr 2015 17:22:09 -0300 Subject: Minor fixes for arrow like change patch Don't use ^ operator yet for compatibility with older compilers. Moved arrow like explanation, and fix precedence description on the text in the manual. Fixed typo in news. --- compiler/parser.nim | 4 ++-- doc/manual/syntax.txt | 7 ++++--- web/news.txt | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 2d363638f..5aeb83495 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -212,8 +212,8 @@ proc getPrecedence(tok: TToken, strongSpaces: bool): int = let relevantChar = tok.ident.s[0] # arrow like? - if L > 1 and tok.ident.s[^1] == '>' and tok.ident.s[^2] in {'-', '~', '='}: - return considerStrongSpaces(1) + if L > 1 and tok.ident.s[L-1] == '>' and + tok.ident.s[L-2] in {'-', '~', '='}: return considerStrongSpaces(1) template considerAsgn(value: expr) = result = if tok.ident.s[L-1] == '=': 1 else: value diff --git a/doc/manual/syntax.txt b/doc/manual/syntax.txt index f6fe0652d..24644bce2 100644 --- a/doc/manual/syntax.txt +++ b/doc/manual/syntax.txt @@ -15,8 +15,6 @@ Associativity Binary operators whose first character is ``^`` are right-associative, all other binary operators are left-associative. -Operators ending in either ``->``, ``~>`` or ``=>`` are called -`arrow like`:idx:. Precedence @@ -33,9 +31,12 @@ as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``. For binary operators that are not keywords the precedence is determined by the following rules: +Operators ending in either ``->``, ``~>`` or ``=>`` are called +`arrow like`:idx:, and have the lowest precedence of all operators. + If the operator ends with ``=`` and its first character is none of ``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which -has the lowest precedence. +has the second lowest precedence. Otherwise precedence is determined by the first character. diff --git a/web/news.txt b/web/news.txt index b5b897c1a..6b109aa1c 100644 --- a/web/news.txt +++ b/web/news.txt @@ -34,7 +34,7 @@ News should be used instead. - ``nim idetools`` has been replaced by a separate tool `nimsuggest`_. - *arrow like* operators are not right associative anymore. - - *arrow like* operators are now required end with either ``->``, ``~>`` or + - *arrow like* operators are now required to end with either ``->``, ``~>`` or ``=>``, not just ``>``. Examples of operators still considered arrow like: ``->``, ``==>``, ``+=>``. On the other hand, the following operators are now considered regular operators again: ``|>``, ``-+>``, etc. -- cgit 1.4.1-2-gfad0 From 9abfc60db441e6d21edbc99f0ef38075fba85f36 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 19 Apr 2015 14:25:16 +0200 Subject: parse 'of' branches for macros properly --- compiler/parser.nim | 11 +++++++++-- tests/macros/tlexerex.nim | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/macros/tlexerex.nim (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index d2831ea46..d600f0f85 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1139,9 +1139,11 @@ proc parseMacroColon(p: var TParser, x: PNode): PNode = 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) - addSon(result, makeStmtList(body)) + stmtList.add body + #addSon(result, makeStmtList(body)) while sameInd(p): var b: PNode case p.tok.tokType @@ -1164,8 +1166,13 @@ proc parseMacroColon(p: var TParser, x: PNode): PNode = eat(p, tkColon) else: break addSon(b, parseStmt(p)) - addSon(result, b) + 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 proc parseExprStmt(p: var TParser): PNode = #| exprStmt = simpleExpr diff --git a/tests/macros/tlexerex.nim b/tests/macros/tlexerex.nim new file mode 100644 index 000000000..d348a4bcc --- /dev/null +++ b/tests/macros/tlexerex.nim @@ -0,0 +1,16 @@ + +import macros + +macro match*(s: cstring|string; pos: int; sections: untyped): untyped = + for sec in sections.children: + expectKind sec, nnkOfBranch + expectLen sec, 2 + result = newStmtList() + +when isMainModule: + var input = "the input" + var pos = 0 + match input, pos: + of r"[a-zA-Z_]\w+": echo "an identifier" + of r"\d+": echo "an integer" + of r".": echo "something else" -- cgit 1.4.1-2-gfad0 From 8a6df889d095ac846decde0a472476f73ebdeb4e Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Tue, 14 Apr 2015 18:30:29 +0200 Subject: Parser: Use colcom(...) when possible This make parsing obligatory colon more consistent across the parser's code. --- compiler/parser.nim | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 7da2f0d22..31db286f7 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -945,8 +945,7 @@ proc parseDoBlock(p: var TParser): PNode = getTok(p) let params = parseParamList(p, retColon=false) let pragmas = optPragmas(p) - eat(p, tkColon) - skipComment(p, result) + colcom(p, result) result = newProcNode(nkDo, info, parseStmt(p), params = params, pragmas = pragmas) @@ -1318,8 +1317,7 @@ proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode = var branch = newNodeP(nkElifBranch, p) optInd(p, branch) addSon(branch, parseExpr(p)) - eat(p, tkColon) - skipComment(p, branch) + colcom(p, branch) addSon(branch, parseStmt(p)) skipComment(p, branch) addSon(result, branch) @@ -1327,8 +1325,7 @@ proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode = if p.tok.tokType == tkElse and sameOrNoInd(p): var branch = newNodeP(nkElse, p) eat(p, tkElse) - eat(p, tkColon) - skipComment(p, branch) + colcom(p, branch) addSon(branch, parseStmt(p)) addSon(result, branch) @@ -1399,8 +1396,7 @@ proc parseTry(p: var TParser; isExpr: bool): PNode = #| (optInd 'finally' colcom stmt)? result = newNodeP(nkTryStmt, p) getTok(p) - eat(p, tkColon) - skipComment(p, result) + colcom(p, result) addSon(result, parseStmt(p)) var b: PNode = nil while sameOrNoInd(p) or isExpr: -- cgit 1.4.1-2-gfad0 From 0da4d6b7551e37683fde683c1433c31ddb788f2c Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Tue, 14 Apr 2015 21:24:35 +0200 Subject: Parser: Make exprList() not comsume endToken This makes use single comcol or eat for multiple cases. Also this makes exprList responsible for consuming only list of expressions, nothing else which is more logical. As a side-effect compiler is now more consistent about errors, eg.: try # <- missing something echo "try" finally: echo "finally" Triggers: test.nim(2, 6) Error: ':' expected try: echo "try" finally # <- missing something echo "finally" Previously triggered: test.nim(4, 6) Error: invalid indentation But now we got: Error: ':' expected - same as in 1st case --- compiler/parser.nim | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index 31db286f7..8f27774ed 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -389,7 +389,6 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - eat(p, endTok) proc dotExpr(p: var TParser, a: PNode): PNode = #| dotExpr = expr '.' optInd symbol @@ -1155,16 +1154,14 @@ proc parseMacroColon(p: var TParser, x: PNode): PNode = getTok(p) optInd(p, b) addSon(b, parseExpr(p)) - eat(p, tkColon) of tkExcept: b = newNodeP(nkExceptBranch, p) exprList(p, tkColon, b) - skipComment(p, b) of tkElse: b = newNodeP(nkElse, p) getTok(p) - eat(p, tkColon) else: break + eat(p, tkColon) addSon(b, parseStmt(p)) addSon(stmtList, b) if b.kind == nkElse: break @@ -1373,13 +1370,11 @@ proc parseCase(p: var TParser): PNode = getTok(p) optInd(p, b) addSon(b, parseExpr(p)) - eat(p, tkColon) of tkElse: b = newNodeP(nkElse, p) getTok(p) - eat(p, tkColon) else: break - skipComment(p, b) + colcom(p, b) addSon(b, parseStmt(p)) addSon(result, b) if b.kind == nkElse: break @@ -1406,10 +1401,9 @@ proc parseTry(p: var TParser; isExpr: bool): PNode = exprList(p, tkColon, b) of tkFinally: b = newNodeP(nkFinally, p) - getTokNoInd(p) - eat(p, tkColon) + getTok(p) else: break - skipComment(p, b) + colcom(p, b) addSon(b, parseStmt(p)) addSon(result, b) if b.kind == nkFinally: break @@ -1418,7 +1412,7 @@ proc parseTry(p: var TParser; isExpr: bool): PNode = proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode = #| exceptBlock = 'except' colcom stmt result = newNodeP(kind, p) - getTokNoInd(p) + getTok(p) colcom(p, result) addSon(result, parseStmt(p)) @@ -1451,7 +1445,7 @@ proc parseStaticOrDefer(p: var TParser; k: TNodeKind): PNode = #| staticStmt = 'static' colcom stmt #| deferStmt = 'defer' colcom stmt result = newNodeP(k, p) - getTokNoInd(p) + getTok(p) colcom(p, result) addSon(result, parseStmt(p)) @@ -1690,9 +1684,8 @@ proc parseObjectCase(p: var TParser): PNode = of tkElse: b = newNodeP(nkElse, p) getTok(p) - eat(p, tkColon) else: break - skipComment(p, b) + colcom(p, b) var fields = parseObjectPart(p) if fields.kind == nkEmpty: parMessage(p, errIdentifierExpected, p.tok) -- cgit 1.4.1-2-gfad0 From 07b13251d173226cd29290935297bc9efee023b8 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Thu, 16 Apr 2015 00:36:42 +0200 Subject: Parser: Fix location (line, col) for diagnostics Previously parser was using lexMessage which was taking location from current buffer position which was pointing after recently consumed token. But since parser shows diagnostics about that token it should point to the location where token starts. This makes diagnostics like: `test.nim(2, 2) Error: ':' expected` point properly at the beginning of the wrong token. --- compiler/lexer.nim | 4 ++++ compiler/parser.nim | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 694d6f4d7..a2db5ac30 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -221,6 +221,10 @@ proc dispMessage(L: TLexer; info: TLineInfo; msg: TMsgKind; arg: string) = proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = L.dispMessage(getLineInfo(L), msg, arg) +proc lexMessageTok*(L: TLexer, msg: TMsgKind, tok: TToken, arg = "") = + var info = newLineInfo(L.fileIdx, tok.line, tok.col) + L.dispMessage(info, msg, arg) + proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = var info = newLineInfo(L.fileIdx, L.lineNumber, pos - L.lineStart) L.dispMessage(info, msg, arg) diff --git a/compiler/parser.nim b/compiler/parser.nim index 7da2f0d22..4516f3603 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -91,7 +91,7 @@ proc closeParser(p: var TParser) = proc parMessage(p: TParser, msg: TMsgKind, arg = "") = ## Produce and emit the parser message `arg` to output. - lexMessage(p.lex, msg, arg) + lexMessageTok(p.lex, msg, p.tok, arg) proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) = ## Produce and emit a parser message to output about the token `tok` @@ -154,7 +154,7 @@ proc eat(p: var TParser, tokType: TTokType) = if p.tok.tokType == tokType: getTok(p) else: - lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType]) + lexMessageTok(p.lex, errTokenExpected, p.tok, TokTypeToStr[tokType]) proc parLineInfo(p: TParser): TLineInfo = ## Retrieve the line information associated with the parser's current state. @@ -1636,7 +1636,7 @@ proc parseEnum(p: var TParser): PNode = p.tok.tokType == tkEof: break if result.len <= 1: - lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok)) + lexMessageTok(p.lex, errIdentifierExpected, p.tok, prettyTok(p.tok)) proc parseObjectPart(p: var TParser): PNode proc parseObjectWhen(p: var TParser): PNode = -- cgit 1.4.1-2-gfad0 From 9e4e7ca5356e08ca69cb82fd0c01c19f8f8f5076 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 24 Apr 2015 12:36:41 +0200 Subject: fixes #2533 --- compiler/parser.nim | 2 +- doc/grammar.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'compiler/parser.nim') diff --git a/compiler/parser.nim b/compiler/parser.nim index c745efb9a..0d2ba7cfc 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1881,7 +1881,7 @@ proc simpleStmt(p: var TParser): PNode = proc complexOrSimpleStmt(p: var TParser): PNode = #| complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt - #| | tryStmt | finallyStmt | exceptStmt | forStmt + #| | tryStmt | forStmt #| | blockStmt | staticStmt | deferStmt | asmStmt #| | 'proc' routine #| | 'method' routine diff --git a/doc/grammar.txt b/doc/grammar.txt index b53515495..72dc6c974 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -179,7 +179,7 @@ simpleStmt = ((returnStmt | raiseStmt | yieldStmt | discardStmt | breakStmt | continueStmt | pragmaStmt | importStmt | exportStmt | fromStmt | includeStmt | commentStmt) / exprStmt) COMMENT? complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt - | tryStmt | finallyStmt | exceptStmt | forStmt + | tryStmt | forStmt | blockStmt | staticStmt | deferStmt | asmStmt | 'proc' routine | 'method' routine -- cgit 1.4.1-2-gfad0