operator precedence changed: assignment like operators are supported; escaping of operators with \ is supported
This commit is contained in:
parent
8c03d96c6a
commit
68be801f63
7 changed files with 64 additions and 26 deletions
|
|
@ -153,20 +153,30 @@ 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 =
|
||||||
|
|
|
||||||
|
|
@ -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)*
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
================ =============================================== ================== ===============
|
================ =============================================== ================== ===============
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
11
tests/accept/run/tprecedence.nim
Normal file
11
tests/accept/run/tprecedence.nim
Normal 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
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
5
todo.txt
5
todo.txt
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue