operator precedence changed: assignment like operators are supported; escaping of operators with \ is supported

This commit is contained in:
Araq 2011-11-09 01:42:05 +01:00
commit 68be801f63
7 changed files with 64 additions and 26 deletions

View file

@ -154,19 +154,29 @@ proc IsLeftAssociative(tok: TToken): bool {.inline.} =
proc getPrecedence(tok: TToken): int = proc getPrecedence(tok: TToken): int =
case tok.tokType case tok.tokType
of tkOpr: of tkOpr:
case tok.ident.s[0] var relevantChar = tok.ident.s[0]
of '$', '^': result = 9 var L = tok.ident.s.len
of '*', '%', '/', '\\': result = 8 if relevantChar == '\\' and L > 1:
of '+', '-', '~', '|': result = 7 relevantChar = tok.ident.s[1]
of '&': result = 6
of '=', '<', '>', '!': result = 4 template considerAsgn(value: expr) =
of '.': result = 5 result = if tok.ident.s[L-1] == '=': 1 else: value
else: result = 1
of tkDiv, tkMod, tkShl, tkShr: result = 8 case relevantChar
of tkIn, tkNotIn, tkIs, tkIsNot, tkNot, tkOf: result = 4 of '$', '^': considerAsgn(10)
of tkDotDot: result = 5 of '*', '%', '/', '\\': considerAsgn(9)
of tkAnd: result = 3 of '~': result = 8
of tkOr, tkXor: result = 2 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 else: result = - 10
proc isOperator(tok: TToken): bool = proc isOperator(tok: TToken): bool =

View file

@ -1,7 +1,7 @@
module ::= ([COMMENT] [SAD] stmt)* module ::= ([COMMENT] [SAD] stmt)*
comma ::= ',' [COMMENT] [IND] 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' | 'or' | 'xor' | 'and'
| 'is' | 'isnot' | 'in' | 'notin' | 'of' | 'is' | 'isnot' | 'in' | 'notin' | 'of'
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..' | 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..'
@ -11,7 +11,8 @@ prefixOperator ::= operator
optInd ::= [COMMENT] [IND] optInd ::= [COMMENT] [IND]
optPar ::= [IND] | [SAD] optPar ::= [IND] | [SAD]
lowestExpr ::= orExpr (OP1 optInd orExpr)* lowestExpr ::= assignExpr (OP0 optInd assignExpr)*
assignExpr ::= orExpr (OP1 optInd orExpr)*
orExpr ::= andExpr (OP2 optInd andExpr)* orExpr ::= andExpr (OP2 optInd andExpr)*
andExpr ::= cmpExpr (OP3 optInd cmpExpr)* andExpr ::= cmpExpr (OP3 optInd cmpExpr)*
cmpExpr ::= sliceExpr (OP4 optInd sliceExpr)* cmpExpr ::= sliceExpr (OP4 optInd sliceExpr)*

View file

@ -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. indentation tokens is already described in the `Lexical Analysis`_ section.
Nimrod allows user-definable operators. Nimrod allows user-definable operators.
Binary operators have 9 different levels of precedence. For user-defined Binary operators have 10 different levels of precedence.
operators, the precedence depends on the first character the operator consists All binary operators are left-associative, except binary operators starting
of. All binary operators are left-associative, except binary operators starting
with (or only consisting of) ``^``. 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 9 (highest) ``$ ^`` OP9
8 ``* / div mod shl shr %`` ``* % \ /`` OP8 8 ``* / div mod shl shr %`` ``* % \ /`` OP8
@ -403,7 +415,8 @@ Precedence level Operators First charact
4 ``== <= < >= > != in not_in is isnot not of`` ``= < > !`` OP4 4 ``== <= < >= > != in not_in is isnot not of`` ``= < > !`` OP4
3 ``and`` OP3 3 ``and`` OP3
2 ``or xor`` OP2 2 ``or xor`` OP2
1 (lowest) ``@ : ?`` OP1 1 ``@ : ?`` OP1
0 (lowest) *assignment operator* (like ``+=``, ``*=``) OP0
================ =============================================== ================== =============== ================ =============================================== ================== ===============

View file

@ -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

View file

@ -417,6 +417,10 @@ proc main() =
var runRes = readResults(runJson) var runRes = readResults(runJson)
listResults(rejectRes, compileRes, runRes) listResults(rejectRes, compileRes, runRes)
outputJSON(rejectRes, compileRes, runRes) outputJSON(rejectRes, compileRes, runRes)
of "dll":
var r = initResults()
runDLLTests r, p.cmdLineRest.string
echo r.data, r
of "test": of "test":
var r = initResults() var r = initResults()
if p.kind != cmdArgument: quit usage if p.kind != cmdArgument: quit usage

View file

@ -4,14 +4,11 @@ Version 0.8.14
- bug: s[1..n] = @[] produces wrong C code - bug: s[1..n] = @[] produces wrong C code
- optimize unused constants away (affected by HLO) - optimize unused constants away (affected by HLO)
- fix actors.nim; test with different thread var implementations - fix actors.nim; test with different thread var implementations
- dead code elim for JS backend
version 0.9.0 version 0.9.0
============= =============
- special precedence rules for assignment operators: If the operator ends with - dead code elim for JS backend; 'of' operator for JS backend
'=' and does **not** start with '<', '>', '!', '=', '~', '?', it is an
assignment operator
- test the sort implementation again - test the sort implementation again
- 'let x = y' - 'let x = y'
- const ptr/ref - const ptr/ref

View file

@ -44,6 +44,8 @@ Changes affecting backwards compatibility
raise hooks. raise hooks.
- Changed exception handling/error reporting for ``os.removeFile`` and - Changed exception handling/error reporting for ``os.removeFile`` and
``os.removeDir``. ``os.removeDir``.
- Operators now have diffent precedence rules: Assignment-like operators
(like ``*=``) are now special-cased.
Language Additions Language Additions