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
parent 8c03d96c6a
commit 68be801f63
7 changed files with 64 additions and 26 deletions

View File

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

View File

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

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.
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
================ =============================================== ================== ===============

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

View File

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

View File

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