174 lines
4.8 KiB
Plaintext
174 lines
4.8 KiB
Plaintext
@preprocessor esmodule
|
|
@{%
|
|
import node from './parseTree/_index.js';
|
|
|
|
import moo from 'moo';
|
|
|
|
const lexer = moo.compile({
|
|
number: /[0-9]+(?:\.[0-9]+)?/,
|
|
string: {
|
|
match: /'[^']*'|"[^"]*"/,
|
|
value: s => s.slice(1, -1).replace('\\n', '\n'),
|
|
},
|
|
name: {
|
|
match: /[~#]?[a-zA-Z]*[a-ce-zA-Z][a-zA-Z0-9_]*/,
|
|
type: moo.keywords({
|
|
'keywords': ['true', 'false'],
|
|
}),
|
|
},
|
|
space: {
|
|
match: /\s+/,
|
|
lineBreaks: true,
|
|
},
|
|
diceOperator: ['d'],
|
|
separator: [',', ';'],
|
|
period: ['.'],
|
|
ifOperator: ['?'],
|
|
elseOperator: [':'],
|
|
multiplicativeOperator: ['*', '/'],
|
|
exponentOperator: ['^'],
|
|
additiveOperator: ['+', '-'],
|
|
moduloOperator: ['%'],
|
|
andOperator: ['&', '&&'],
|
|
orOperator: ['|', '||'],
|
|
stringDelimiters: ['\"', '\''],
|
|
equalityOperator: ['=', '==', '===', '!=', '!=='],
|
|
notOperator: ['!'],
|
|
relationalOperator: ['>', '<', '>=', '<='],
|
|
brackets: ['(', ')', '{', '}', '[', ']'],
|
|
});
|
|
|
|
function nuller() { return null; }
|
|
function operator([left, _1, operator, _2, right], fn){
|
|
return node.operator.create({
|
|
left,
|
|
right,
|
|
operator: operator.value,
|
|
fn
|
|
});
|
|
}
|
|
%}
|
|
|
|
# Use the Moo lexer
|
|
@lexer lexer
|
|
|
|
spacedExpression ->
|
|
_ expression _ {% d => d[1] %}
|
|
|
|
expression ->
|
|
ifStatement {% id %}
|
|
|
|
ifStatement ->
|
|
orExpression _ %ifOperator _ orExpression _ %elseOperator _ ifStatement {%
|
|
d => node.if.create({condition: d[0], consequent: d[4], alternative: d[8]})
|
|
%}
|
|
| orExpression {% id %}
|
|
|
|
orExpression ->
|
|
orExpression _ %orOperator _ andExpression {% d => operator(d, 'or') %}
|
|
| andExpression {% id %}
|
|
|
|
andExpression ->
|
|
andExpression _ %andOperator _ equalityExpression {% d => operator(d, 'and') %}
|
|
| equalityExpression {% id %}
|
|
|
|
equalityExpression ->
|
|
equalityExpression _ %equalityOperator _ relationalExpression {% d => operator(d, 'equality') %}
|
|
| relationalExpression {% id %}
|
|
|
|
relationalExpression ->
|
|
relationalExpression _ %relationalOperator _ additiveExpression {% d => operator(d, 'relation') %}
|
|
| additiveExpression {% id %}
|
|
|
|
additiveExpression ->
|
|
additiveExpression _ %additiveOperator _ remainderExpression {% d => operator(d, 'add') %}
|
|
| remainderExpression {% id %}
|
|
|
|
remainderExpression ->
|
|
remainderExpression _ %moduloOperator _ multiplicativeExpression {% d => operator(d, 'remainder') %}
|
|
| multiplicativeExpression {% id %}
|
|
|
|
multiplicativeExpression ->
|
|
multiplicativeExpression _ %multiplicativeOperator _ rollExpression {% d => operator(d, 'multiply') %}
|
|
| rollExpression {% id %}
|
|
|
|
rollExpression ->
|
|
rollExpression _ %diceOperator _ exponentExpression {% d => node.roll.create({left: d[0], right: d[4]}) %}
|
|
| singleRollExpression {% id %}
|
|
|
|
singleRollExpression ->
|
|
"d" _ singleRollExpression {% d => node.roll.create({left: node.constant.create({value: 1}), right: d[2]}) %}
|
|
| exponentExpression {% id %}
|
|
|
|
exponentExpression ->
|
|
callExpression _ %exponentOperator _ exponentExpression {% d => operator(d, 'exponent') %}
|
|
| unaryExpression {% id %}
|
|
|
|
unaryExpression ->
|
|
%additiveOperator _ unaryExpression {% d => node.unaryOperator.create({operator: d[0].value, right: d[2]})%}
|
|
| notExpression {% id %}
|
|
|
|
notExpression ->
|
|
%notOperator _ notExpression {% d => node.not.create({right: d[2]})%}
|
|
| callExpression {% id %}
|
|
|
|
callExpression ->
|
|
name _ arguments {%
|
|
d => node.call.create({functionName: d[0].name, args: d[2]})
|
|
%}
|
|
| indexExpression {% id %}
|
|
|
|
arguments ->
|
|
"(" _ (expression {% d => d[0] %}) ( _ %separator _ expression {% d => d[3] %} ):* _ ")" {%
|
|
d => [d[2], ...d[3]]
|
|
%}
|
|
| "(" _ ")" {% d => [] %}
|
|
|
|
indexExpression ->
|
|
indexExpression "[" _ expression _ "]" {% d => node.index.create({array: d[0], index: d[3]}) %}
|
|
| arrayExpression {% id %}
|
|
|
|
arrayExpression ->
|
|
"[" _ (expression {% d => d[0] %}) ( _ %separator _ expression {% d => d[3] %} ):* _ "]" {%
|
|
d => node.array.create({ values: [d[2], ...d[3]] })
|
|
%}
|
|
| "[" _ "]" {% d => node.array.create({ values: [] }) %}
|
|
| parenthesizedExpression {% id %}
|
|
|
|
parenthesizedExpression ->
|
|
"(" _ expression _ ")" {% d => node.parenthesis.create({content: d[2]}) %}
|
|
| accessorExpression {% id %}
|
|
|
|
accessorExpression ->
|
|
(%name {% d => d[0].value %}) ( "." keyExpression {% d => d[1] %} ):+ {%
|
|
d=> node.accessor.create({name: d[0], path: d[1]})
|
|
%}
|
|
| valueExpression {% id %}
|
|
|
|
keyExpression -> name {% d => d[0].name %}
|
|
| number {% d => d[0].value %}
|
|
|
|
valueExpression ->
|
|
name {% id %}
|
|
| number {% id %}
|
|
| string {% id %}
|
|
| boolean {% id %}
|
|
|
|
# A number or a function of a number
|
|
number ->
|
|
%number {% d => node.constant.create({value: +d[0].value}) %}
|
|
|
|
name ->
|
|
%name {% d => node.symbol.create({name: d[0].value}) %}
|
|
|
|
string ->
|
|
%string {% d => node.constant.create({value: d[0].value}) %}
|
|
|
|
boolean ->
|
|
"true" {% d => node.constant.create({value: true}) %}
|
|
| "false" {% d => node.constant.create({value: false}) %}
|
|
|
|
_ ->
|
|
null
|
|
| %space {% nuller %}
|