SPEC change: ^ is right-assoc and of highest priority
This commit is contained in:
parent
ceb1f5e218
commit
19fbc8a55e
4 changed files with 38 additions and 26 deletions
|
|
@ -368,19 +368,20 @@ indentation tokens is already described in the `Lexical Analysis`_ section.
|
||||||
Nimrod allows user-definable operators.
|
Nimrod allows user-definable operators.
|
||||||
Binary operators have 8 different levels of precedence. For user-defined
|
Binary operators have 8 different levels of precedence. For user-defined
|
||||||
operators, the precedence depends on the first character the operator consists
|
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
|
Precedence level Operators First characters Terminal symbol
|
||||||
================ ============================================== ================== ===============
|
================ ============================================== ================== ===============
|
||||||
7 (highest) ``$`` OP7
|
7 (highest) ``$ ^`` OP7
|
||||||
6 ``* / div mod shl shr %`` ``* % \ /`` OP6
|
6 ``* / div mod shl shr %`` ``* % \ /`` OP6
|
||||||
5 ``+ -`` ``+ ~ |`` OP5
|
5 ``+ -`` ``+ ~ |`` OP5
|
||||||
4 ``&`` ``&`` OP4
|
4 ``&`` ``&`` OP4
|
||||||
3 ``== <= < >= > != in not_in is isnot`` ``= < > !`` OP3
|
3 ``== <= < >= > != in not_in is isnot`` ``= < > !`` OP3
|
||||||
2 ``and`` OP2
|
2 ``and`` OP2
|
||||||
1 ``or xor`` OP1
|
1 ``or xor`` OP1
|
||||||
0 (lowest) ``? @ ^ ` : .`` OP0
|
0 (lowest) ``? @ ` : .`` OP0
|
||||||
================ ============================================== ================== ===============
|
================ ============================================== ================== ===============
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1530,6 +1531,7 @@ Example:
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The statements after the `try`:idx: are executed in sequential order unless
|
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
|
an exception ``e`` is raised. If the exception type of ``e`` matches any
|
||||||
of the list ``exceptlist`` the corresponding statements are executed.
|
of the list ``exceptlist`` the corresponding statements are executed.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -145,11 +145,14 @@ proc parseStmt(p: var TParser): PNode
|
||||||
proc parseTypeDesc(p: var TParser): PNode
|
proc parseTypeDesc(p: var TParser): PNode
|
||||||
proc parseParamList(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 =
|
proc getPrecedence(tok: PToken): int =
|
||||||
case tok.tokType
|
case tok.tokType
|
||||||
of tkOpr:
|
of tkOpr:
|
||||||
case tok.ident.s[0]
|
case tok.ident.s[0]
|
||||||
of '$': result = 7
|
of '$', '^': result = 7
|
||||||
of '*', '%', '/', '\\': result = 6
|
of '*', '%', '/', '\\': result = 6
|
||||||
of '+', '-', '~', '|': result = 5
|
of '+', '-', '~', '|': result = 5
|
||||||
of '&': result = 4
|
of '&': result = 4
|
||||||
|
|
@ -159,7 +162,7 @@ proc getPrecedence(tok: PToken): int =
|
||||||
of tkIn, tkNotIn, tkIs, tkIsNot: result = 3
|
of tkIn, tkNotIn, tkIs, tkIsNot: result = 3
|
||||||
of tkAnd: result = 2
|
of tkAnd: result = 2
|
||||||
of tkOr, tkXor: result = 1
|
of tkOr, tkXor: result = 1
|
||||||
else: result = - 1
|
else: result = - 10
|
||||||
|
|
||||||
proc isOperator(tok: PToken): bool =
|
proc isOperator(tok: PToken): bool =
|
||||||
result = getPrecedence(tok) >= 0
|
result = getPrecedence(tok) >= 0
|
||||||
|
|
@ -386,14 +389,10 @@ proc parseAddr(p: var TParser): PNode =
|
||||||
|
|
||||||
proc setBaseFlags(n: PNode, base: TNumericalBase) =
|
proc setBaseFlags(n: PNode, base: TNumericalBase) =
|
||||||
case base
|
case base
|
||||||
of base10:
|
of base10: nil
|
||||||
nil
|
of base2: incl(n.flags, nfBase2)
|
||||||
of base2:
|
of base8: incl(n.flags, nfBase8)
|
||||||
incl(n.flags, nfBase2)
|
of base16: incl(n.flags, nfBase16)
|
||||||
of base8:
|
|
||||||
incl(n.flags, nfBase8)
|
|
||||||
of base16:
|
|
||||||
incl(n.flags, nfBase16)
|
|
||||||
|
|
||||||
proc identOrLiteral(p: var TParser): PNode =
|
proc identOrLiteral(p: var TParser): PNode =
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
|
|
@ -475,7 +474,7 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||||
result = parseAddr(p)
|
result = parseAddr(p)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errExprExpected, tokToStr(p.tok))
|
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
|
result = nil
|
||||||
|
|
||||||
proc primary(p: var TParser): PNode =
|
proc primary(p: var TParser): PNode =
|
||||||
|
|
@ -520,25 +519,23 @@ proc primary(p: var TParser): PNode =
|
||||||
else: break
|
else: break
|
||||||
|
|
||||||
proc lowestExprAux(p: var TParser, v: var PNode, limit: int): PToken =
|
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'
|
v = primary(p) # expand while operators have priorities higher than 'limit'
|
||||||
op = p.tok
|
var op = p.tok
|
||||||
opPred = getPrecedence(p.tok)
|
var opPrec = getPrecedence(op)
|
||||||
while (opPred > limit):
|
while opPrec >= limit:
|
||||||
node = newNodeP(nkInfix, p)
|
var leftAssoc = ord(IsLeftAssociative(op))
|
||||||
opNode = newIdentNodeP(op.ident, p) # skip operator:
|
var node = newNodeP(nkInfix, p)
|
||||||
|
var opNode = newIdentNodeP(op.ident, p) # skip operator:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, opNode) # read sub-expression with higher priority
|
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, opNode)
|
||||||
addSon(node, v)
|
addSon(node, v)
|
||||||
addSon(node, v2)
|
addSon(node, v2)
|
||||||
v = node
|
v = node
|
||||||
op = nextop
|
op = nextop
|
||||||
opPred = getPrecedence(nextop)
|
opPrec = getPrecedence(nextop)
|
||||||
result = op # return first untreated operator
|
result = op # return first untreated operator
|
||||||
|
|
||||||
proc lowestExpr(p: var TParser): PNode =
|
proc lowestExpr(p: var TParser): PNode =
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ tnestprc.nim;10
|
||||||
toop1.nim;34[]o 5
|
toop1.nim;34[]o 5
|
||||||
topenarrayrepr.nim;5 - [1]
|
topenarrayrepr.nim;5 - [1]
|
||||||
topenlen.nim;7
|
topenlen.nim;7
|
||||||
|
toprprec.nim;done
|
||||||
toverflw.nim;the computation overflowed
|
toverflw.nim;the computation overflowed
|
||||||
toverflw2.nim;Error: unhandled exception: over- or underflow [EOverflow]
|
toverflw2.nim;Error: unhandled exception: over- or underflow [EOverflow]
|
||||||
toverl2.nim;true012
|
toverl2.nim;true012
|
||||||
|
|
|
||||||
|
12
tests/accept/run/toprprec.nim
Normal file
12
tests/accept/run/toprprec.nim
Normal file
|
|
@ -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"
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue