diff --git a/app/imports/parser/grammar.js b/app/imports/parser/grammar.js index 01336eb1..c1672285 100644 --- a/app/imports/parser/grammar.js +++ b/app/imports/parser/grammar.js @@ -13,6 +13,7 @@ function id(x) { return x[0]; } import RollNode from '/imports/parser/parseTree/RollNode.js'; import SymbolNode from '/imports/parser/parseTree/SymbolNode.js'; import UnaryOperatorNode from '/imports/parser/parseTree/UnaryOperatorNode.js'; + import NotOperatorNode from '/imports/parser/parseTree/NotOperatorNode.js'; import moo from 'moo'; @@ -37,6 +38,7 @@ function id(x) { return x[0]; } ternaryOperator: ['?', ':'], multiplicativeOperator: ['*', '/'], exponentOperator: ['^'], + notOperator: ['!'], additiveOperator: ['+', '-'], andOperator: ['&', '&&'], orOperator: ['|', '||'], @@ -81,7 +83,9 @@ let ParserRules = [ {"name": "exponentExpression", "symbols": ["callExpression", "_", (lexer.has("exponentOperator") ? {type: "exponentOperator"} : exponentOperator), "_", "exponentExpression"], "postprocess": d => operator(d, 'exponent')}, {"name": "exponentExpression", "symbols": ["unaryExpression"], "postprocess": id}, {"name": "unaryExpression", "symbols": [(lexer.has("additiveOperator") ? {type: "additiveOperator"} : additiveOperator), "_", "unaryExpression"], "postprocess": d => new UnaryOperatorNode({operator: d[0].value, right: d[2]})}, - {"name": "unaryExpression", "symbols": ["callExpression"], "postprocess": id}, + {"name": "unaryExpression", "symbols": ["notExpression"], "postprocess": id}, + {"name": "notExpression", "symbols": [(lexer.has("notOperator") ? {type: "notOperator"} : notOperator), "_", "notExpression"], "postprocess": d => new NotOperatorNode({right: d[2]})}, + {"name": "notExpression", "symbols": ["callExpression"], "postprocess": id}, {"name": "callExpression", "symbols": ["name", "_", "arguments"], "postprocess": d => new CallNode ({functionName: d[0].name, args: d[2]}) }, diff --git a/app/imports/parser/grammar.ne b/app/imports/parser/grammar.ne index f2039bc1..7f768c39 100644 --- a/app/imports/parser/grammar.ne +++ b/app/imports/parser/grammar.ne @@ -11,6 +11,7 @@ import RollNode from '/imports/parser/parseTree/RollNode.js'; import SymbolNode from '/imports/parser/parseTree/SymbolNode.js'; import UnaryOperatorNode from '/imports/parser/parseTree/UnaryOperatorNode.js'; + import NotOperatorNode from '/imports/parser/parseTree/NotOperatorNode.js'; import moo from 'moo'; @@ -35,6 +36,7 @@ ternaryOperator: ['?', ':'], multiplicativeOperator: ['*', '/'], exponentOperator: ['^'], + notOperator: ['!'], additiveOperator: ['+', '-'], andOperator: ['&', '&&'], orOperator: ['|', '||'], @@ -105,6 +107,10 @@ exponentExpression -> unaryExpression -> %additiveOperator _ unaryExpression {% d => new UnaryOperatorNode({operator: d[0].value, right: d[2]})%} +| notExpression {% id %} + +notExpression -> + %notOperator _ notExpression {% d => new NotOperatorNode({right: d[2]})%} | callExpression {% id %} callExpression -> diff --git a/app/imports/parser/parseTree/NotOperatorNode.js b/app/imports/parser/parseTree/NotOperatorNode.js new file mode 100644 index 00000000..e1ef4f62 --- /dev/null +++ b/app/imports/parser/parseTree/NotOperatorNode.js @@ -0,0 +1,27 @@ +import ParseNode from '/imports/parser/parseTree/ParseNode.js'; +import ConstantNode from '/imports/parser/parseTree/ConstantNode.js'; + +export default class NotOperatorNode extends ParseNode { + constructor({right}) { + super(...arguments); + this.right = right; + } + resolve(fn, scope, context){ + let rightNode = this.right[fn](scope, context); + if (!(rightNode instanceof ConstantNode)){ + return new NotOperatorNode({ + right: rightNode, + }); + } + let right = rightNode.value; + let result = !right; + return new ConstantNode({ + value: result, + type: typeof result, + }); + } + toString(){ + let {right} = this; + return `!${right.toString()}`; + } +} diff --git a/app/imports/parser/parseTree/OperatorNode.js b/app/imports/parser/parseTree/OperatorNode.js index 8d609f41..376dddc5 100644 --- a/app/imports/parser/parseTree/OperatorNode.js +++ b/app/imports/parser/parseTree/OperatorNode.js @@ -13,7 +13,7 @@ export default class OperatorNode extends ParseNode { let leftNode = this.left[fn](scope, context); let rightNode = this.right[fn](scope, context); let left, right; - if (leftNode.type !== 'number' || rightNode.type !== 'number'){ + if (!(leftNode instanceof ConstantNode) || !(rightNode instanceof ConstantNode)){ return new OperatorNode({ left: leftNode, right: rightNode,