Began writing a custom parser for calculations
This commit is contained in:
1
parser/.gitignore
vendored
Normal file
1
parser/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
node_modules
|
||||||
0
parser/grammar.html
Normal file
0
parser/grammar.html
Normal file
80
parser/grammar.js
Normal file
80
parser/grammar.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Generated automatically by nearley, version 2.16.0
|
||||||
|
// http://github.com/Hardmath123/nearley
|
||||||
|
(function () {
|
||||||
|
function id(x) { return x[0]; }
|
||||||
|
|
||||||
|
const moo = require("moo");
|
||||||
|
|
||||||
|
const lexer = moo.compile({
|
||||||
|
number: /[0-9]+(?:\.[0-9]+)?/,
|
||||||
|
name: {match: /[a-zA-Z]+\w*?/, type: moo.keywords({
|
||||||
|
'keywords': ['if', 'else', 'd'],
|
||||||
|
})},
|
||||||
|
space: {match: /\s+/, lineBreaks: true},
|
||||||
|
separators: [',', '.'],
|
||||||
|
multiplicativeOperator: ['*', '/'],
|
||||||
|
exponentOperator: ['^'],
|
||||||
|
additiveOperator: ['+', '-'],
|
||||||
|
unaryOperator: ['-'],
|
||||||
|
andOperator: ['&', '&&'],
|
||||||
|
orOperator: ['|', '||'],
|
||||||
|
equalityOperator: ['=', '==', '===', '!=', '!=='],
|
||||||
|
relationalOperator: ['>', '<', '>=', '<='],
|
||||||
|
brackets: {match: ['(', ')', '{', '}'], value: () => null},
|
||||||
|
});
|
||||||
|
|
||||||
|
function nuller() { return null; }
|
||||||
|
|
||||||
|
function operator([left, _1, op, _2, right]){
|
||||||
|
return {type: 'operation', operator: op.value, left, right};
|
||||||
|
}
|
||||||
|
var grammar = {
|
||||||
|
Lexer: lexer,
|
||||||
|
ParserRules: [
|
||||||
|
{"name": "ifStatement", "symbols": [{"literal":"if"}, "_", {"literal":"("}, "_", "callExpression", "_", {"literal":")"}, "_", "ifStatement", "_", {"literal":"else"}, "_", "ifStatement"], "postprocess": d => ({condition: d[4], true: d[8], false: d[12]})},
|
||||||
|
{"name": "ifStatement", "symbols": ["callExpression"], "postprocess": id},
|
||||||
|
{"name": "callExpression", "symbols": ["name", "_", "arguments"], "postprocess":
|
||||||
|
d => ({type: "call", function: d[0], arguments: d[2]})
|
||||||
|
},
|
||||||
|
{"name": "callExpression", "symbols": ["expression"], "postprocess": id},
|
||||||
|
{"name": "arguments$ebnf$1$subexpression$1", "symbols": ["expression"], "postprocess": d => d[0]},
|
||||||
|
{"name": "arguments$ebnf$1", "symbols": ["arguments$ebnf$1$subexpression$1"], "postprocess": id},
|
||||||
|
{"name": "arguments$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
|
||||||
|
{"name": "arguments$ebnf$2", "symbols": []},
|
||||||
|
{"name": "arguments$ebnf$2$subexpression$1", "symbols": ["_", {"literal":","}, "_", "expression"], "postprocess": d => d[3]},
|
||||||
|
{"name": "arguments$ebnf$2", "symbols": ["arguments$ebnf$2", "arguments$ebnf$2$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
|
||||||
|
{"name": "arguments", "symbols": [{"literal":"("}, "_", "arguments$ebnf$1", "arguments$ebnf$2", "_", {"literal":")"}], "postprocess":
|
||||||
|
d => [d[2], ...d[3]]
|
||||||
|
},
|
||||||
|
{"name": "expression", "symbols": ["equalityExpression"], "postprocess": id},
|
||||||
|
{"name": "equalityExpression", "symbols": ["equalityExpression", "_", (lexer.has("equalityOperator") ? {type: "equalityOperator"} : equalityOperator), "_", "relationalExpression"], "postprocess": operator},
|
||||||
|
{"name": "equalityExpression", "symbols": ["relationalExpression"], "postprocess": id},
|
||||||
|
{"name": "relationalExpression", "symbols": ["relationalExpression", "_", (lexer.has("relationalOperator") ? {type: "relationalOperator"} : relationalOperator), "_", "additiveExpression"], "postprocess": operator},
|
||||||
|
{"name": "relationalExpression", "symbols": ["additiveExpression"], "postprocess": id},
|
||||||
|
{"name": "orExpression", "symbols": ["orExpression", "_", (lexer.has("orOperator") ? {type: "orOperator"} : orOperator), "_", "andExpression"], "postprocess": operator},
|
||||||
|
{"name": "orExpression", "symbols": ["andExpression"], "postprocess": id},
|
||||||
|
{"name": "andExpression", "symbols": ["andExpression", "_", (lexer.has("andOperator") ? {type: "andOperator"} : andOperator), "_", "equalityExpression"], "postprocess": operator},
|
||||||
|
{"name": "andExpression", "symbols": ["equalityExpression"], "postprocess": id},
|
||||||
|
{"name": "additiveExpression", "symbols": ["additiveExpression", "_", (lexer.has("additiveOperator") ? {type: "additiveOperator"} : additiveOperator), "_", "rollExpression"], "postprocess": operator},
|
||||||
|
{"name": "additiveExpression", "symbols": ["rollExpression"], "postprocess": id},
|
||||||
|
{"name": "rollExpression", "symbols": ["rollExpression", "_", {"literal":"d"}, "_", "multiplicativeExpression"], "postprocess": operator},
|
||||||
|
{"name": "rollExpression", "symbols": ["multiplicativeExpression"], "postprocess": id},
|
||||||
|
{"name": "multiplicativeExpression", "symbols": ["multiplicativeExpression", "_", (lexer.has("multiplicativeOperator") ? {type: "multiplicativeOperator"} : multiplicativeOperator), "_", "exponentExpression"], "postprocess": operator},
|
||||||
|
{"name": "multiplicativeExpression", "symbols": ["exponentExpression"], "postprocess": id},
|
||||||
|
{"name": "exponentExpression", "symbols": ["exponentExpression", "_", (lexer.has("exponentOperator") ? {type: "exponentOperator"} : exponentOperator), "_", "valueExpression"], "postprocess": operator},
|
||||||
|
{"name": "exponentExpression", "symbols": ["valueExpression"], "postprocess": id},
|
||||||
|
{"name": "valueExpression", "symbols": ["name"], "postprocess": id},
|
||||||
|
{"name": "valueExpression", "symbols": ["number"], "postprocess": id},
|
||||||
|
{"name": "number", "symbols": [(lexer.has("number") ? {type: "number"} : number)], "postprocess": d => d[0].value},
|
||||||
|
{"name": "name", "symbols": [(lexer.has("name") ? {type: "name"} : name)], "postprocess": d => d[0].value},
|
||||||
|
{"name": "_", "symbols": []},
|
||||||
|
{"name": "_", "symbols": [(lexer.has("space") ? {type: "space"} : space)], "postprocess": nuller}
|
||||||
|
]
|
||||||
|
, ParserStart: "ifStatement"
|
||||||
|
}
|
||||||
|
if (typeof module !== 'undefined'&& typeof module.exports !== 'undefined') {
|
||||||
|
module.exports = grammar;
|
||||||
|
} else {
|
||||||
|
window.grammar = grammar;
|
||||||
|
}
|
||||||
|
})();
|
||||||
98
parser/grammar.ne
Normal file
98
parser/grammar.ne
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
@{%
|
||||||
|
const moo = require("moo");
|
||||||
|
|
||||||
|
const lexer = moo.compile({
|
||||||
|
number: /[0-9]+(?:\.[0-9]+)?/,
|
||||||
|
name: {match: /[a-zA-Z]+\w*?/, type: moo.keywords({
|
||||||
|
'keywords': ['if', 'else', 'd'],
|
||||||
|
})},
|
||||||
|
space: {match: /\s+/, lineBreaks: true},
|
||||||
|
separators: [',', '.'],
|
||||||
|
multiplicativeOperator: ['*', '/'],
|
||||||
|
exponentOperator: ['^'],
|
||||||
|
additiveOperator: ['+', '-'],
|
||||||
|
unaryOperator: ['-'],
|
||||||
|
andOperator: ['&', '&&'],
|
||||||
|
orOperator: ['|', '||'],
|
||||||
|
equalityOperator: ['=', '==', '===', '!=', '!=='],
|
||||||
|
relationalOperator: ['>', '<', '>=', '<='],
|
||||||
|
brackets: {match: ['(', ')', '{', '}'], value: () => null},
|
||||||
|
});
|
||||||
|
%}
|
||||||
|
|
||||||
|
@{% function nuller() { return null; } %}
|
||||||
|
|
||||||
|
@{%
|
||||||
|
function operator([left, _1, op, _2, right]){
|
||||||
|
return {type: 'operation', operator: op.value, left, right};
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
# Use the Moo lexer
|
||||||
|
@lexer lexer
|
||||||
|
|
||||||
|
ifStatement ->
|
||||||
|
"if" _ "(" _ callExpression _ ")" _ ifStatement _ "else" _ ifStatement {% d => ({condition: d[4], true: d[8], false: d[12]}) %}
|
||||||
|
| callExpression {% id %}
|
||||||
|
|
||||||
|
callExpression ->
|
||||||
|
name _ arguments
|
||||||
|
{%
|
||||||
|
d => ({type: "call", function: d[0], arguments: d[2]})
|
||||||
|
%}
|
||||||
|
| expression {% id %}
|
||||||
|
|
||||||
|
arguments ->
|
||||||
|
"(" _ (expression {% d => d[0] %}):? ( _ "," _ expression {% d => d[3] %} ):* _ ")"
|
||||||
|
{%
|
||||||
|
d => [d[2], ...d[3]]
|
||||||
|
%}
|
||||||
|
|
||||||
|
expression -> equalityExpression {% id %}
|
||||||
|
|
||||||
|
equalityExpression ->
|
||||||
|
equalityExpression _ %equalityOperator _ relationalExpression {%operator%}
|
||||||
|
| relationalExpression {% id %}
|
||||||
|
|
||||||
|
relationalExpression ->
|
||||||
|
relationalExpression _ %relationalOperator _ additiveExpression {%operator%}
|
||||||
|
| additiveExpression {% id %}
|
||||||
|
|
||||||
|
orExpression ->
|
||||||
|
orExpression _ %orOperator _ andExpression {%operator%}
|
||||||
|
| andExpression {% id %}
|
||||||
|
|
||||||
|
andExpression ->
|
||||||
|
andExpression _ %andOperator _ equalityExpression {%operator%}
|
||||||
|
| equalityExpression {% id %}
|
||||||
|
|
||||||
|
additiveExpression ->
|
||||||
|
additiveExpression _ %additiveOperator _ rollExpression {%operator%}
|
||||||
|
| rollExpression {% id %}
|
||||||
|
|
||||||
|
rollExpression ->
|
||||||
|
rollExpression _ "d" _ multiplicativeExpression {% operator %}
|
||||||
|
| multiplicativeExpression {% id %}
|
||||||
|
|
||||||
|
multiplicativeExpression ->
|
||||||
|
multiplicativeExpression _ %multiplicativeOperator _ exponentExpression {%operator%}
|
||||||
|
| exponentExpression {% id %}
|
||||||
|
|
||||||
|
exponentExpression ->
|
||||||
|
exponentExpression _ %exponentOperator _ valueExpression {%operator%}
|
||||||
|
| valueExpression {% id %}
|
||||||
|
|
||||||
|
valueExpression ->
|
||||||
|
name {% id %}
|
||||||
|
| number {% id %}
|
||||||
|
|
||||||
|
# A number or a function of a number
|
||||||
|
number ->
|
||||||
|
%number {% d => d[0].value %}
|
||||||
|
|
||||||
|
name ->
|
||||||
|
%name {% d => d[0].value %}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
null
|
||||||
|
| %space {% nuller %}
|
||||||
75
parser/package-lock.json
generated
Normal file
75
parser/package-lock.json
generated
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "dicecloud-parser",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"commander": {
|
||||||
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"discontinuous-range": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"moo": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-AMv6iqhTEd5vT/cQlH6cammKS5ekyHhyqTRKi5zKMWl1RTyFnQ3ohPSBNSm8ySe2wlxSKwDonr9D5ZT44mdO3g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"nearley": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"commander": "2.19.0",
|
||||||
|
"moo": "0.4.3",
|
||||||
|
"railroad-diagrams": "1.0.0",
|
||||||
|
"randexp": "0.4.6",
|
||||||
|
"semver": "5.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"moo": {
|
||||||
|
"version": "0.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz",
|
||||||
|
"integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"railroad-diagrams": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"randexp": {
|
||||||
|
"version": "0.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
|
||||||
|
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"discontinuous-range": "1.0.0",
|
||||||
|
"ret": "0.1.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ret": {
|
||||||
|
"version": "0.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||||
|
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
|
||||||
|
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
parser/package.json
Normal file
14
parser/package.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "dicecloud-parser",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nearleyc grammar.ne -o grammar.js",
|
||||||
|
"test": "nearley-test grammar.js",
|
||||||
|
"unparse": "nearley-unparse grammar.js"
|
||||||
|
},
|
||||||
|
"author": "Stefan Zermatten",
|
||||||
|
"devDependencies": {
|
||||||
|
"moo": "^0.5.0",
|
||||||
|
"nearley": "^2.16.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user