diff options
author | Araq <rumpf_a@web.de> | 2011-01-10 21:28:48 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-01-10 21:28:48 +0100 |
commit | 19fbc8a55edb009e216ab8954fde906dec6b738a (patch) | |
tree | f6796114c5053c39ffa9a785a5b1682c4d903c6f | |
parent | ceb1f5e218075196cd3b7d40973249e419db8ebf (diff) | |
download | Nim-19fbc8a55edb009e216ab8954fde906dec6b738a.tar.gz |
SPEC change: ^ is right-assoc and of highest priority
-rwxr-xr-x | doc/manual.txt | 8 | ||||
-rwxr-xr-x | rod/pnimsyn.nim | 43 | ||||
-rwxr-xr-x | tests/accept/run/spec.csv | 1 | ||||
-rw-r--r-- | tests/accept/run/toprprec.nim | 12 |
4 files changed, 38 insertions, 26 deletions
diff --git a/doc/manual.txt b/doc/manual.txt index 4aed263cc..299cf5b0f 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -368,19 +368,20 @@ indentation tokens is already described in the `Lexical Analysis`_ section. Nimrod allows user-definable operators. Binary operators have 8 different levels of precedence. For user-defined operators, the precedence depends on the first character the operator consists -of. All binary operators are left-associative. +of. All binary operators are left-associative, except binary operator starting +with (or only consisting of) ``^``. ================ ============================================== ================== =============== Precedence level Operators First characters Terminal symbol ================ ============================================== ================== =============== - 7 (highest) ``$`` OP7 + 7 (highest) ``$ ^`` OP7 6 ``* / div mod shl shr %`` ``* % \ /`` OP6 5 ``+ -`` ``+ ~ |`` OP5 4 ``&`` ``&`` OP4 3 ``== <= < >= > != in not_in is isnot`` ``= < > !`` OP3 2 ``and`` OP2 1 ``or xor`` OP1 - 0 (lowest) ``? @ ^ ` : .`` OP0 + 0 (lowest) ``? @ ` : .`` OP0 ================ ============================================== ================== =============== @@ -1530,6 +1531,7 @@ Example: close(f) + The statements after the `try`:idx: are executed in sequential order unless an exception ``e`` is raised. If the exception type of ``e`` matches any of the list ``exceptlist`` the corresponding statements are executed. diff --git a/rod/pnimsyn.nim b/rod/pnimsyn.nim index 766e01671..fe80fe0c4 100755 --- a/rod/pnimsyn.nim +++ b/rod/pnimsyn.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -145,11 +145,14 @@ proc parseStmt(p: var TParser): PNode proc parseTypeDesc(p: var TParser): PNode proc parseParamList(p: var TParser): PNode +proc IsLeftAssociative(tok: PToken): bool {.inline.} = + result = tok.tokType != tkOpr or tok.ident.s[0] != '^' + proc getPrecedence(tok: PToken): int = case tok.tokType of tkOpr: case tok.ident.s[0] - of '$': result = 7 + of '$', '^': result = 7 of '*', '%', '/', '\\': result = 6 of '+', '-', '~', '|': result = 5 of '&': result = 4 @@ -159,7 +162,7 @@ proc getPrecedence(tok: PToken): int = of tkIn, tkNotIn, tkIs, tkIsNot: result = 3 of tkAnd: result = 2 of tkOr, tkXor: result = 1 - else: result = - 1 + else: result = - 10 proc isOperator(tok: PToken): bool = result = getPrecedence(tok) >= 0 @@ -386,14 +389,10 @@ proc parseAddr(p: var TParser): PNode = proc setBaseFlags(n: PNode, base: TNumericalBase) = case base - of base10: - nil - of base2: - incl(n.flags, nfBase2) - of base8: - incl(n.flags, nfBase8) - of base16: - incl(n.flags, nfBase16) + of base10: nil + of base2: incl(n.flags, nfBase2) + of base8: incl(n.flags, nfBase8) + of base16: incl(n.flags, nfBase16) proc identOrLiteral(p: var TParser): PNode = case p.tok.tokType @@ -475,7 +474,7 @@ proc identOrLiteral(p: var TParser): PNode = result = parseAddr(p) else: parMessage(p, errExprExpected, tokToStr(p.tok)) - getTok(p) # we must consume a token here to prevend endless loops! + getTok(p) # we must consume a token here to prevend endless loops! result = nil proc primary(p: var TParser): PNode = @@ -520,25 +519,23 @@ proc primary(p: var TParser): PNode = else: break proc lowestExprAux(p: var TParser, v: var PNode, limit: int): PToken = - var - op, nextop: PToken - opPred: int - v2, node, opNode: PNode v = primary(p) # expand while operators have priorities higher than 'limit' - op = p.tok - opPred = getPrecedence(p.tok) - while (opPred > limit): - node = newNodeP(nkInfix, p) - opNode = newIdentNodeP(op.ident, p) # skip operator: + var op = p.tok + var opPrec = getPrecedence(op) + while opPrec >= limit: + var leftAssoc = ord(IsLeftAssociative(op)) + var node = newNodeP(nkInfix, p) + var opNode = newIdentNodeP(op.ident, p) # skip operator: getTok(p) optInd(p, opNode) # read sub-expression with higher priority - nextop = lowestExprAux(p, v2, opPred) + var v2: PNode + var nextop = lowestExprAux(p, v2, opPrec + leftAssoc) addSon(node, opNode) addSon(node, v) addSon(node, v2) v = node op = nextop - opPred = getPrecedence(nextop) + opPrec = getPrecedence(nextop) result = op # return first untreated operator proc lowestExpr(p: var TParser): PNode = diff --git a/tests/accept/run/spec.csv b/tests/accept/run/spec.csv index 075e4e67e..980301bd0 100755 --- a/tests/accept/run/spec.csv +++ b/tests/accept/run/spec.csv @@ -49,6 +49,7 @@ tnestprc.nim;10 toop1.nim;34[]o 5 topenarrayrepr.nim;5 - [1] topenlen.nim;7 +toprprec.nim;done toverflw.nim;the computation overflowed toverflw2.nim;Error: unhandled exception: over- or underflow [EOverflow] toverl2.nim;true012 diff --git a/tests/accept/run/toprprec.nim b/tests/accept/run/toprprec.nim new file mode 100644 index 000000000..4728b2e68 --- /dev/null +++ b/tests/accept/run/toprprec.nim @@ -0,0 +1,12 @@ +# Test operator precedence: + +assert 3+5*5-2 == 28- -26-28 + +proc `^-` (x, y: int): int = + # now right-associative! + result = x - y + +assert 34 ^- 6 ^- 2 == 30 +assert 34 - 6 - 2 == 26 +echo "done" + |