diff options
-rwxr-xr-x | compiler/parser.nim | 38 | ||||
-rwxr-xr-x | doc/grammar.txt | 5 | ||||
-rwxr-xr-x | doc/manual.txt | 25 | ||||
-rw-r--r-- | tests/accept/run/tprecedence.nim | 11 | ||||
-rwxr-xr-x | tests/tester.nim | 4 | ||||
-rwxr-xr-x | todo.txt | 5 | ||||
-rwxr-xr-x | web/news.txt | 2 |
7 files changed, 64 insertions, 26 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 13c7a3edb..361c297fb 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -153,20 +153,30 @@ proc IsLeftAssociative(tok: TToken): bool {.inline.} = proc getPrecedence(tok: TToken): int = case tok.tokType - of tkOpr: - case tok.ident.s[0] - of '$', '^': result = 9 - of '*', '%', '/', '\\': result = 8 - of '+', '-', '~', '|': result = 7 - of '&': result = 6 - of '=', '<', '>', '!': result = 4 - of '.': result = 5 - else: result = 1 - of tkDiv, tkMod, tkShl, tkShr: result = 8 - of tkIn, tkNotIn, tkIs, tkIsNot, tkNot, tkOf: result = 4 - of tkDotDot: result = 5 - of tkAnd: result = 3 - of tkOr, tkXor: result = 2 + of tkOpr: + var relevantChar = tok.ident.s[0] + var L = tok.ident.s.len + if relevantChar == '\\' and L > 1: + relevantChar = tok.ident.s[1] + + template considerAsgn(value: expr) = + result = if tok.ident.s[L-1] == '=': 1 else: value + + case relevantChar + of '$', '^': considerAsgn(10) + of '*', '%', '/', '\\': considerAsgn(9) + of '~': result = 8 + of '+', '-', '|': considerAsgn(8) + of '&': considerAsgn(7) + of '=', '<', '>', '!': result = 5 + of '.': considerAsgn(6) + of '?': result = 2 + else: considerAsgn(2) + of tkDiv, tkMod, tkShl, tkShr: result = 9 + of tkIn, tkNotIn, tkIs, tkIsNot, tkNot, tkOf: result = 5 + of tkDotDot: result = 6 + of tkAnd: result = 4 + of tkOr, tkXor: result = 3 else: result = - 10 proc isOperator(tok: TToken): bool = diff --git a/doc/grammar.txt b/doc/grammar.txt index 458c85833..5f7b851fa 100755 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -1,7 +1,7 @@ module ::= ([COMMENT] [SAD] stmt)* comma ::= ',' [COMMENT] [IND] -operator ::= OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 +operator ::= OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 | 'or' | 'xor' | 'and' | 'is' | 'isnot' | 'in' | 'notin' | 'of' | 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..' @@ -11,7 +11,8 @@ prefixOperator ::= operator optInd ::= [COMMENT] [IND] optPar ::= [IND] | [SAD] -lowestExpr ::= orExpr (OP1 optInd orExpr)* +lowestExpr ::= assignExpr (OP0 optInd assignExpr)* +assignExpr ::= orExpr (OP1 optInd orExpr)* orExpr ::= andExpr (OP2 optInd andExpr)* andExpr ::= cmpExpr (OP3 optInd cmpExpr)* cmpExpr ::= sliceExpr (OP4 optInd sliceExpr)* diff --git a/doc/manual.txt b/doc/manual.txt index 44bd99352..6d8286dd7 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -387,13 +387,25 @@ This section lists Nimrod's standard syntax in ENBF. How the parser receives indentation tokens is already described in the `Lexical Analysis`_ section. Nimrod allows user-definable operators. -Binary operators have 9 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, except binary operators starting -with (or only consisting of) ``^``. +Binary operators have 10 different levels of precedence. +All binary operators are left-associative, except binary operators starting +with (or only consisting of) ``^``. + +For operators that are not keywords the precedence is determined by the +following rules: + +An operator symbol's *relevant character* is its first +character unless the first character is ``\`` and its length is greater than 1 +then it is the second character. + +If the operator ends with ``=`` and its relevant character is none of +``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which +has the lowest precedence. + +Otherwise precedence is determined by the relevant character. ================ =============================================== ================== =============== -Precedence level Operators First characters Terminal symbol +Precedence level Operators Relevant character Terminal symbol ================ =============================================== ================== =============== 9 (highest) ``$ ^`` OP9 8 ``* / div mod shl shr %`` ``* % \ /`` OP8 @@ -403,7 +415,8 @@ Precedence level Operators First charact 4 ``== <= < >= > != in not_in is isnot not of`` ``= < > !`` OP4 3 ``and`` OP3 2 ``or xor`` OP2 - 1 (lowest) ``@ : ?`` OP1 + 1 ``@ : ?`` OP1 + 0 (lowest) *assignment operator* (like ``+=``, ``*=``) OP0 ================ =============================================== ================== =============== diff --git a/tests/accept/run/tprecedence.nim b/tests/accept/run/tprecedence.nim new file mode 100644 index 000000000..6b1b250a2 --- /dev/null +++ b/tests/accept/run/tprecedence.nim @@ -0,0 +1,11 @@ +discard """ + output: "true" +""" + +# Test the new predence rules + +proc `\+` (x, y: int): int = result = x + y +proc `\*` (x, y: int): int = result = x * y + +echo 5 \+ 1 \* 9 == 14 + diff --git a/tests/tester.nim b/tests/tester.nim index 9741d7719..2baffc81d 100755 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -417,6 +417,10 @@ proc main() = var runRes = readResults(runJson) listResults(rejectRes, compileRes, runRes) outputJSON(rejectRes, compileRes, runRes) + of "dll": + var r = initResults() + runDLLTests r, p.cmdLineRest.string + echo r.data, r of "test": var r = initResults() if p.kind != cmdArgument: quit usage diff --git a/todo.txt b/todo.txt index e0fa4d015..608d55b7a 100755 --- a/todo.txt +++ b/todo.txt @@ -4,14 +4,11 @@ Version 0.8.14 - bug: s[1..n] = @[] produces wrong C code - optimize unused constants away (affected by HLO) - fix actors.nim; test with different thread var implementations -- dead code elim for JS backend version 0.9.0 ============= -- special precedence rules for assignment operators: If the operator ends with - '=' and does **not** start with '<', '>', '!', '=', '~', '?', it is an - assignment operator +- dead code elim for JS backend; 'of' operator for JS backend - test the sort implementation again - 'let x = y' - const ptr/ref diff --git a/web/news.txt b/web/news.txt index 555b3ef69..d1334ef6f 100755 --- a/web/news.txt +++ b/web/news.txt @@ -44,6 +44,8 @@ Changes affecting backwards compatibility raise hooks. - Changed exception handling/error reporting for ``os.removeFile`` and ``os.removeDir``. +- Operators now have diffent precedence rules: Assignment-like operators + (like ``*=``) are now special-cased. Language Additions |