summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-01-10 21:28:48 +0100
committerAraq <rumpf_a@web.de>2011-01-10 21:28:48 +0100
commit19fbc8a55edb009e216ab8954fde906dec6b738a (patch)
treef6796114c5053c39ffa9a785a5b1682c4d903c6f
parentceb1f5e218075196cd3b7d40973249e419db8ebf (diff)
downloadNim-19fbc8a55edb009e216ab8954fde906dec6b738a.tar.gz
SPEC change: ^ is right-assoc and of highest priority
-rwxr-xr-xdoc/manual.txt8
-rwxr-xr-xrod/pnimsyn.nim43
-rwxr-xr-xtests/accept/run/spec.csv1
-rw-r--r--tests/accept/run/toprprec.nim12
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"
+