-
Notifications
You must be signed in to change notification settings - Fork 4
/
expressions.ne
96 lines (72 loc) · 4.2 KB
/
expressions.ne
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@lexer lexer
expression -> tupleExpression {% id %}
| returnExpression {% id %}
| "imp" _ identifier {% from(ast.ImportFile) %}
| "imp" _ string {% from(ast.ImportFile) %}
returnExpression -> "return" _ expression {% from(ast.Return) %}
funcExpr -> arguments (_ "->" _) type (_ "{" _) block (_ "}") {% from(ast.Function) %}
arguments -> "[" (_ typeVarsDeclaration):? (_ definiteDeclaration (__ definiteDeclaration):*):? (_ "]") {% from(ast.Arguments) %}
tupleExpression -> noCommaExpression {% id %}
| (noCommaExpression _ "," _):+ noCommaExpression (_ ","):? {% from(ast.Tuple) %}
noCommaExpression -> pipeExpression {% id %}
pipeExpression -> pipeRhs {% id %}
| pipeOperation {% id %}
pipeOperation -> pipeExpression _ "|>" _ pipeRhs {% operation(ast.Operator.PIPE) %}
# RHS = right hand side
pipeRhs -> booleanExpression {% id %}
| ifExpression {% id %}
| funcExpr {% id %}
booleanExpression -> notExpression {% id %}
| notExpression _ ("&&" | "&") _ booleanExpression {% operation(ast.Operator.AND) %}
| notExpression _ ("||" | "|") _ booleanExpression {% operation(ast.Operator.OR) %}
notExpression -> compareExpression {% id %}
| "not" _ notExpression {% prefix(ast.UnaryOperator.NOT) %}
compareExpression -> sumExpression {% id %}
| (sumExpression _ compareOperator _):+ sumExpression {% from(ast.Comparisons) %}
compareOperator -> ("==" | "=") {% ([token]) => ({ ...token[0], value: ast.Compare.EQUAL }) %}
| ">" {% ([token]) => ({ ...token, value: ast.Compare.GREATER }) %}
| "<" {% ([token]) => ({ ...token, value: ast.Compare.LESS }) %}
| ">=" {% ([token]) => ({ ...token, value: ast.Compare.GEQ }) %}
| "<=" {% ([token]) => ({ ...token, value: ast.Compare.LEQ }) %}
| ("!=" | "/=") {% ([token]) => ({ ...token[0], value: ast.Compare.NEQ }) %}
sumExpression -> productExpression {% id %}
| sumExpression _ "+" _ productExpression {% operation(ast.Operator.ADD) %}
| sumExpression _ "-" _ productExpression {% operation(ast.Operator.MINUS) %}
productExpression -> exponentExpression {% id %}
| productExpression _ "*" _ exponentExpression {% operation(ast.Operator.MULTIPLY) %}
| productExpression _ "/" _ exponentExpression {% operation(ast.Operator.DIVIDE) %}
| productExpression _ "%" _ exponentExpression {% operation(ast.Operator.MODULO) %}
exponentExpression -> prefixExpression {% id %}
| exponentExpression _ "^" _ prefixExpression {% operation(ast.Operator.EXPONENT) %}
prefixExpression -> postfixExpression {% id %}
| "-" _ prefixExpression {% prefix(ast.UnaryOperator.NEGATE) %}
| "~" _ prefixExpression {% prefix(ast.UnaryOperator.NOT) %}
postfixExpression -> value {% id %}
| postfixExpressionImpure {% id %}
| postfixExpression (_ "." _) anyIdentifier {% from(ast.RecordAccess) %}
# A newline would be ok after `type`, but I think it's better to be
# symmetrical with ordinary function call.
# Notably, `type("hi", "hello")` will return "str, str" rather than being a
# type error.
| ("type" _spaces "(" _) expression (_ ")") {% from(ast.TypeCall) %}
postfixExpressionImpure -> postfixExpression _ "!" {% suffix(ast.UnaryOperator.AWAIT) %}
# No newlines allowed between the function and its arguments
| postfixExpression (_spaces "(" _) ((noCommaExpression (_ "," _)):* noCommaExpression ((_ ","):? _)):? ")" {% from(ast.FuncCall) %}
# Generally, values are the same as expressions except they require some form of
# enclosing brackets for more complex expressions, which can help avoid syntax
# ambiguities.
value -> identifier {% id %}
| %number {% from(ast.Number) %}
| %float {% from(ast.Float) %}
| string {% id %}
| %char {% from(ast.Char) %}
| "(" _ ")" {% from(ast.Unit) %}
| "(" _ expression _ ")" {% includeBrackets %}
| ("[" _) ((noCommaExpression (_ "," _)):* noCommaExpression ((_ ","):? _)):? "]" {% from(ast.List) %}
| ("{" _) ((recordEntry blockSeparator):* recordEntry (blockSeparator | _spaces)):? "}" {% from(ast.Record) %}
recordEntry -> anyIdentifier (_ ":" _) expression {% from(ast.RecordEntry) %}
| identifier {% from(ast.RecordEntry) %}
string -> %string {% from(ast.String) %}
ifExpression -> ("if" _) condition (_ "{" _) expression (_ "}" _ "else" _) elseExprBranch {% from(ast.IfExpression) %}
elseExprBranch -> "{" _ expression _ "}" {% includeBrackets %}
| ifExpression {% id %}