Continued work on parser, now calling functions and rolling correctly
This commit is contained in:
@@ -79,7 +79,7 @@ let ParserRules = [
|
|||||||
{"name": "exponentExpression", "symbols": ["callExpression", "_", (lexer.has("exponentOperator") ? {type: "exponentOperator"} : exponentOperator), "_", "exponentExpression"], "postprocess": d => operator(d, 'exponent')},
|
{"name": "exponentExpression", "symbols": ["callExpression", "_", (lexer.has("exponentOperator") ? {type: "exponentOperator"} : exponentOperator), "_", "exponentExpression"], "postprocess": d => operator(d, 'exponent')},
|
||||||
{"name": "exponentExpression", "symbols": ["callExpression"], "postprocess": id},
|
{"name": "exponentExpression", "symbols": ["callExpression"], "postprocess": id},
|
||||||
{"name": "callExpression", "symbols": ["name", "_", "arguments"], "postprocess":
|
{"name": "callExpression", "symbols": ["name", "_", "arguments"], "postprocess":
|
||||||
d => new CallNode ({type: "call", fn: d[0], arguments: d[2]})
|
d => new CallNode ({functionName: d[0].name, args: d[2]})
|
||||||
},
|
},
|
||||||
{"name": "callExpression", "symbols": ["indexExpression"], "postprocess": id},
|
{"name": "callExpression", "symbols": ["indexExpression"], "postprocess": id},
|
||||||
{"name": "arguments$ebnf$1$subexpression$1", "symbols": ["expression"], "postprocess": d => d[0]},
|
{"name": "arguments$ebnf$1$subexpression$1", "symbols": ["expression"], "postprocess": d => d[0]},
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ exponentExpression ->
|
|||||||
|
|
||||||
callExpression ->
|
callExpression ->
|
||||||
name _ arguments {%
|
name _ arguments {%
|
||||||
d => new CallNode ({type: "call", fn: d[0], arguments: d[2]})
|
d => new CallNode ({functionName: d[0].name, args: d[2]})
|
||||||
%}
|
%}
|
||||||
| indexExpression {% id %}
|
| indexExpression {% id %}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
|||||||
|
|
||||||
export default class ArrayNode extends ParseNode {
|
export default class ArrayNode extends ParseNode {
|
||||||
constructor({values}) {
|
constructor({values}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
compile(){
|
compile(scope){
|
||||||
let values = this.values.map(node => node.compile());
|
let values = this.values.map(node => node.compile(scope));
|
||||||
return new ArrayNode({values});
|
return new ArrayNode({values, previousNodes: [this]});
|
||||||
}
|
}
|
||||||
toString(){
|
toString(){
|
||||||
return `[${this.values.map(node => node.toString()).join(', ')}]`;
|
return `[${this.values.map(node => node.toString()).join(', ')}]`;
|
||||||
|
|||||||
@@ -1 +1,82 @@
|
|||||||
//TODO
|
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||||
|
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
|
||||||
|
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||||
|
|
||||||
|
export default class CallNode extends ParseNode {
|
||||||
|
constructor({functionName, args}) {
|
||||||
|
super(...arguments);
|
||||||
|
this.functionName = functionName;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
compile(scope){
|
||||||
|
return this.resolve('compile', scope);
|
||||||
|
}
|
||||||
|
roll(scope){
|
||||||
|
return this.resolve('roll', scope);
|
||||||
|
}
|
||||||
|
reduce(scope){
|
||||||
|
return this.resolve('reduce', scope);
|
||||||
|
}
|
||||||
|
resolve(fn, scope){
|
||||||
|
let func = functions[this.functionName];
|
||||||
|
if (!func) return new ErrorNode({
|
||||||
|
node: this,
|
||||||
|
error: `${this.functionName} is not a function`,
|
||||||
|
previousNodes: [this],
|
||||||
|
});
|
||||||
|
let args = castArgsToType({fn, scope, args: this.args, type: func.argumentType});
|
||||||
|
if (args.failed){
|
||||||
|
if (fn === 'reduce'){
|
||||||
|
return new ErrorNode({
|
||||||
|
node: this,
|
||||||
|
error: 'Could not convert all arguments to the correct type',
|
||||||
|
previousNodes: [this],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return new CallNode({
|
||||||
|
functionName: this.functionName,
|
||||||
|
args: args,
|
||||||
|
previousNodes: [this],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let value = func.fn.apply(null, args);
|
||||||
|
console.log({args})
|
||||||
|
return new ConstantNode({
|
||||||
|
value,
|
||||||
|
type: 'number',
|
||||||
|
previousNodes: [this],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
toString(){
|
||||||
|
return `${this.functionName}(${this.args.map(node => node.toString()).join(', ')})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const functions = {
|
||||||
|
'min': {
|
||||||
|
comment: 'Returns the lowest of the given numbers',
|
||||||
|
argumentType: 'number',
|
||||||
|
resultType: 'number',
|
||||||
|
fn: Math.min,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function castArgsToType({fn, scope, args, type}){
|
||||||
|
let resolvedArgs = args.map(node => node[fn](scope))
|
||||||
|
let result = [];
|
||||||
|
if (type === 'number'){
|
||||||
|
resolvedArgs.forEach(node => {
|
||||||
|
if (node.isNumber){
|
||||||
|
result.push(node.value);
|
||||||
|
} else {
|
||||||
|
resolvedArgs.failed = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (resolvedArgs.failed) return resolvedArgs;
|
||||||
|
console.log({result})
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||||
|
|
||||||
export default class ConstantNode extends ParseNode {
|
export default class ConstantNode extends ParseNode {
|
||||||
constructor({value, type, errors}){
|
constructor({value, type, rollTable}){
|
||||||
super();
|
super(...arguments);
|
||||||
// string, number, boolean, numberArray, uncompiledNode
|
// string, number, boolean, numberArray, uncompiledNode
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
if (errors) this.errors = errors;
|
if (rollTable) this.rollTable = rollTable;
|
||||||
}
|
}
|
||||||
compile(){
|
compile(){
|
||||||
return this;
|
return this;
|
||||||
@@ -18,6 +18,6 @@ export default class ConstantNode extends ParseNode {
|
|||||||
return this.type === 'number';
|
return this.type === 'number';
|
||||||
}
|
}
|
||||||
get isInteger(){
|
get isInteger(){
|
||||||
return this.isNumberNode && Number.isInteger(this.value);
|
return this.type === 'number' && Number.isInteger(this.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
|||||||
|
|
||||||
export default class ErrorNode extends ParseNode {
|
export default class ErrorNode extends ParseNode {
|
||||||
constructor({node, error}) {
|
constructor({node, error}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.error = error;
|
this.error = error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||||
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
|
||||||
|
|
||||||
export default class IfNode extends ParseNode {
|
export default class IfNode extends ParseNode {
|
||||||
constructor({condition, consequent, alternative}){
|
constructor({condition, consequent, alternative}){
|
||||||
super();
|
super(...arguments);
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
this.consequent = consequent;
|
this.consequent = consequent;
|
||||||
this.alternative = alternative;
|
this.alternative = alternative;
|
||||||
@@ -12,33 +11,26 @@ export default class IfNode extends ParseNode {
|
|||||||
let {condition, consequent, alternative} = this;
|
let {condition, consequent, alternative} = this;
|
||||||
return `${condition.toString()} ? ${consequent.toString()} : ${alternative.toString()}`
|
return `${condition.toString()} ? ${consequent.toString()} : ${alternative.toString()}`
|
||||||
}
|
}
|
||||||
compile(){
|
compile(scope){
|
||||||
let condition = this.condition.compile();
|
return this.resolve('compile', scope);
|
||||||
let consequent = this.consequent.compile();
|
}
|
||||||
let alternative = this.alternative.compile();
|
roll(scope){
|
||||||
if (
|
return this.resolve('roll', scope);
|
||||||
condition.type !== 'string' &&
|
}
|
||||||
condition.type !== 'number' &&
|
reduce(scope){
|
||||||
condition.type !== 'boolean'
|
return this.resolve('reduce', scope);
|
||||||
){
|
}
|
||||||
// Handle unresolved condition
|
resolve(fn, scope){
|
||||||
return new ConstantNode({
|
let condition = this.condition[fn](scope);
|
||||||
value: `${condition.value}) ${consequent.value} else ${alternative.value}`,
|
let consequent = this.consequent[fn](scope);
|
||||||
type: 'uncompiledNode',
|
let alternative = this.alternative[fn](scope);
|
||||||
errors: [
|
this.resolve(condition, consequent, alternative);
|
||||||
...condition.errors,
|
if (condition.value){
|
||||||
...consequent.errors,
|
consequent.inheritDetails([condition, this]);
|
||||||
...alternative.errors,
|
return consequent;
|
||||||
],
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// So long as the condition reolves, return the correct alternative,
|
alternative.inheritDetails([condition, this]);
|
||||||
// even if it's unresolved
|
return alternative;
|
||||||
if (condition.value){
|
|
||||||
return consequent;
|
|
||||||
} else {
|
|
||||||
return alternative;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,35 @@ import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
|||||||
|
|
||||||
export default class IndexNode extends ParseNode {
|
export default class IndexNode extends ParseNode {
|
||||||
constructor({array, index}) {
|
constructor({array, index}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.array = array;
|
this.array = array;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
compile(){
|
resolve(fn, scope){
|
||||||
let index = this.index.compile();
|
let index = this.index[fn](scope);
|
||||||
if (index.constructor.name === 'ConstantNode' && index.type === 'number'){
|
if (index.isInteger){
|
||||||
let selection = this.array.values[index.value];
|
let selection = this.array.values[index.value - 1];
|
||||||
if (selection){
|
if (selection){
|
||||||
return selection.compile();
|
let result = selection[fn](scope);
|
||||||
|
result.inheritDetails([index, this]);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new IndexNode({
|
return new IndexNode({
|
||||||
array: this.array.compile(),
|
array: this.array[fn](scope),
|
||||||
index: this.index.compile(),
|
index: this.index[fn](scope),
|
||||||
|
previousNodes: [this],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
compile(scope){
|
||||||
|
return this.resolve('compile', scope);
|
||||||
|
}
|
||||||
|
roll(scope){
|
||||||
|
return this.resolve('roll', scope);
|
||||||
|
}
|
||||||
|
reduce(scope){
|
||||||
|
return this.resolve('reduce', scope);
|
||||||
|
}
|
||||||
toString(){
|
toString(){
|
||||||
return `${this.array.toString()}[${this.index.toString()}]`;
|
return `${this.array.toString()}[${this.index.toString()}]`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,22 +3,32 @@ import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
|||||||
|
|
||||||
export default class OperatorNode extends ParseNode {
|
export default class OperatorNode extends ParseNode {
|
||||||
constructor({left, right, operator, fn}) {
|
constructor({left, right, operator, fn}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
}
|
}
|
||||||
compile(){
|
compile(scope){
|
||||||
let leftNode = this.left.compile();
|
return this.resolve('compile', scope);
|
||||||
let rightNode = this.right.compile();
|
}
|
||||||
|
roll(scope){
|
||||||
|
return this.resolve('roll', scope);
|
||||||
|
}
|
||||||
|
reduce(scope){
|
||||||
|
return this.resolve('reduce', scope);
|
||||||
|
}
|
||||||
|
resolve(fn, scope){
|
||||||
|
let leftNode = this.left[fn](scope);
|
||||||
|
let rightNode = this.right[fn](scope);
|
||||||
let left, right;
|
let left, right;
|
||||||
if (leftNode.type !== 'number' || rightNode.type !== 'number'){
|
if (leftNode.type !== 'number' || rightNode.type !== 'number'){
|
||||||
return new OperatorNode({
|
return new OperatorNode({
|
||||||
left: leftNode,
|
left: leftNode,
|
||||||
right: rightNode,
|
right: rightNode,
|
||||||
operator: this.operator,
|
operator: this.operator,
|
||||||
fn: this.fn
|
fn: this.fn,
|
||||||
|
previousNodes: [this],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
left = leftNode.value;
|
left = leftNode.value;
|
||||||
@@ -44,7 +54,11 @@ export default class OperatorNode extends ParseNode {
|
|||||||
case '>=': result = left >= right; break;
|
case '>=': result = left >= right; break;
|
||||||
case '<=': result = left <= right; break;
|
case '<=': result = left <= right; break;
|
||||||
}
|
}
|
||||||
return new ConstantNode({value: result, type: typeof result});
|
return new ConstantNode({
|
||||||
|
value: result,
|
||||||
|
type: typeof result,
|
||||||
|
previousNodes: [this, leftNode, rightNode],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
toString(){
|
toString(){
|
||||||
let {left, right, operator} = this;
|
let {left, right, operator} = this;
|
||||||
|
|||||||
@@ -2,15 +2,24 @@ import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
|||||||
|
|
||||||
export default class ParenthesisNode extends ParseNode {
|
export default class ParenthesisNode extends ParseNode {
|
||||||
constructor({content}) {
|
constructor({content}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
compile(){
|
compile(scope){
|
||||||
let content = this.content.compile();
|
return this.resolve('compile', scope);
|
||||||
|
}
|
||||||
|
roll(scope){
|
||||||
|
return this.resolve('roll', scope);
|
||||||
|
}
|
||||||
|
reduce(scope){
|
||||||
|
return this.resolve('reduce', scope);
|
||||||
|
}
|
||||||
|
resolve(fn, scope){
|
||||||
|
let content = this.content[fn](scope);
|
||||||
if (content.constructor.name === 'ConstantNode'){
|
if (content.constructor.name === 'ConstantNode'){
|
||||||
return content;
|
return content;
|
||||||
} else {
|
} else {
|
||||||
return new ParenthesisNode({content});
|
return new ParenthesisNode({content, previousNodes: [this]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toString(){
|
toString(){
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
export default class ParseNode {
|
export default class ParseNode {
|
||||||
|
constructor({previousNodes, detail}){
|
||||||
|
this.inheritDetails(previousNodes);
|
||||||
|
if (detail) this.pushDetails([detail]);
|
||||||
|
}
|
||||||
|
inheritDetails(nodes){
|
||||||
|
if (!nodes || !nodes.length) return;
|
||||||
|
nodes.forEach(node => this.pushDetails(node.details));
|
||||||
|
}
|
||||||
|
pushDetails(details){
|
||||||
|
if (!details || !details.length) return;
|
||||||
|
if (!this.details) this.details = [];
|
||||||
|
details.forEach(detail => this.details.push(detail));
|
||||||
|
}
|
||||||
compile(){
|
compile(){
|
||||||
// Returns a ParseNode, a ConstantNode if possible
|
// Returns a ParseNode, a ConstantNode if possible
|
||||||
throw new Meteor.Error('Compile not implemented on ' + this.constructor.name);
|
throw new Meteor.Error('Compile not implemented on ' + this.constructor.name);
|
||||||
@@ -7,11 +20,11 @@ export default class ParseNode {
|
|||||||
throw new Meteor.Error('toString not implemented on ' + this.constructor.name);
|
throw new Meteor.Error('toString not implemented on ' + this.constructor.name);
|
||||||
}
|
}
|
||||||
// Compile, but turn rolls into arrays
|
// Compile, but turn rolls into arrays
|
||||||
roll(){
|
roll(scope){
|
||||||
return this.compile();
|
return this.compile(scope);
|
||||||
}
|
}
|
||||||
// Compile, turn rolls into arrays, and reduce those arrays into single values
|
// Compile, turn rolls into arrays, and reduce those arrays into single values
|
||||||
reduce(){
|
reduce(scope){
|
||||||
return this.roll();
|
return this.roll(scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||||
|
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||||
|
|
||||||
export default class RollArrayNode extends ParseNode {
|
export default class RollArrayNode extends ParseNode {
|
||||||
constructor({values}) {
|
constructor({values}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
compile(){
|
compile(){
|
||||||
@@ -12,6 +13,11 @@ export default class RollArrayNode extends ParseNode {
|
|||||||
return `[${this.values.join(', ')}]`;
|
return `[${this.values.join(', ')}]`;
|
||||||
}
|
}
|
||||||
reduce(){
|
reduce(){
|
||||||
//TODO sum and return values
|
let total = this.values.reduce((a, b) => a + b);
|
||||||
|
return new ConstantNode({
|
||||||
|
value: total,
|
||||||
|
type: 'number',
|
||||||
|
previousNodes: [this],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||||
import ArrayNode from '/imports/parser/parseTree/ArrayNode.js';
|
import RollArrayNode from '/imports/parser/parseTree/RollArrayNode.js';
|
||||||
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
|
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
|
||||||
|
|
||||||
export default class RollNode extends ParseNode {
|
export default class RollNode extends ParseNode {
|
||||||
constructor({left, right}) {
|
constructor({left, right}) {
|
||||||
super();
|
super(...arguments);
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
}
|
}
|
||||||
compile(){
|
compile(scope){
|
||||||
let left = this.left.compile();
|
let left = this.left.compile(scope);
|
||||||
let right = this.right.compile();
|
let right = this.right.compile(scope);
|
||||||
return new RollNode({left, right});
|
return new RollNode({left, right, previousNodes: [this]});
|
||||||
}
|
}
|
||||||
toString(){
|
toString(){
|
||||||
if (
|
if (
|
||||||
@@ -22,19 +22,21 @@ export default class RollNode extends ParseNode {
|
|||||||
return `${this.left.toString()}d${this.right.toString()}`;
|
return `${this.left.toString()}d${this.right.toString()}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
roll(){
|
roll(scope){
|
||||||
let left = this.left.reduce();
|
let left = this.left.reduce(scope);
|
||||||
let right = this.right.reduce();
|
let right = this.right.reduce(scope);
|
||||||
if (!left.isInteger){
|
if (!left.isInteger){
|
||||||
return new ErrorNode({
|
return new ErrorNode({
|
||||||
node: this,
|
node: this,
|
||||||
error: 'Number of dice is not an integer'
|
error: 'Number of dice is not an integer',
|
||||||
|
previousNodes: [this, left, right],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!right.isInteger){
|
if (!right.isInteger){
|
||||||
return new ErrorNode({
|
return new ErrorNode({
|
||||||
node: this,
|
node: this,
|
||||||
error: 'Dice size is not an integer'
|
error: 'Dice size is not an integer',
|
||||||
|
previousNodes: [this, left, right],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let number = left.value;
|
let number = left.value;
|
||||||
@@ -44,14 +46,18 @@ export default class RollNode extends ParseNode {
|
|||||||
});
|
});
|
||||||
let diceSize = right.value;
|
let diceSize = right.value;
|
||||||
let randomSrc = DDP.randomStream('diceRoller');
|
let randomSrc = DDP.randomStream('diceRoller');
|
||||||
let rolls = [];
|
let values = [];
|
||||||
for (let i = 0; i < number; i++){
|
for (let i = 0; i < number; i++){
|
||||||
let roll = ~~(randomSrc.fraction() * diceSize) + 1
|
let roll = ~~(randomSrc.fraction() * diceSize) + 1
|
||||||
rolls.push(roll);
|
values.push(roll);
|
||||||
}
|
}
|
||||||
return new ArrayNode({values: rolls});
|
return new RollArrayNode({
|
||||||
|
values,
|
||||||
|
detail: {number, diceSize, values},
|
||||||
|
previousNodes: [this, left, right],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
reduce(){
|
reduce(scope){
|
||||||
this.roll().reduce();
|
return this.roll(scope).reduce(scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||||
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||||
|
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
|
||||||
|
|
||||||
export default class SymbolNode extends ParseNode {
|
export default class SymbolNode extends ParseNode {
|
||||||
constructor({name}){
|
constructor({name}){
|
||||||
super();
|
super(...arguments);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
toString(){
|
toString(){
|
||||||
@@ -13,12 +14,11 @@ export default class SymbolNode extends ParseNode {
|
|||||||
let value = scope && scope[this.name];
|
let value = scope && scope[this.name];
|
||||||
let type = typeof value;
|
let type = typeof value;
|
||||||
if (type === 'string' || type === 'number' || type === 'boolean'){
|
if (type === 'string' || type === 'number' || type === 'boolean'){
|
||||||
return new ConstantNode({value, type});
|
return new ConstantNode({value, type, previousNodes: [this]});
|
||||||
} else if (type === 'undefined'){
|
} else if (type === 'undefined'){
|
||||||
return new ConstantNode({
|
return new ErrorNode({
|
||||||
value: this.name,
|
node: this,
|
||||||
type: 'uncompiledNode',
|
error: `${this.name} could not be resolved`,
|
||||||
errors: [`${this.name} could not be resolved`]
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Meteor.Error(`Unexpected case: ${this.name} resolved to ${value}`);
|
throw new Meteor.Error(`Unexpected case: ${this.name} resolved to ${value}`);
|
||||||
|
|||||||
@@ -18,6 +18,21 @@
|
|||||||
readonly
|
readonly
|
||||||
label="compiled"
|
label="compiled"
|
||||||
/>
|
/>
|
||||||
|
<v-text-field
|
||||||
|
v-model="rolled"
|
||||||
|
readonly
|
||||||
|
label="rolled"
|
||||||
|
/>
|
||||||
|
<v-text-field
|
||||||
|
v-model="reduced"
|
||||||
|
readonly
|
||||||
|
label="reduced"
|
||||||
|
/>
|
||||||
|
<v-textarea
|
||||||
|
v-model="reducedJson"
|
||||||
|
readonly
|
||||||
|
label="reduced"
|
||||||
|
/>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,6 +47,9 @@ export default {
|
|||||||
output: null,
|
output: null,
|
||||||
compiled: null,
|
compiled: null,
|
||||||
string: null,
|
string: null,
|
||||||
|
rolled: null,
|
||||||
|
reduced: null,
|
||||||
|
reducedJson: null,
|
||||||
}},
|
}},
|
||||||
watch: {
|
watch: {
|
||||||
input(val){
|
input(val){
|
||||||
@@ -41,7 +59,11 @@ export default {
|
|||||||
this.output = JSON.stringify(output, null, 2);
|
this.output = JSON.stringify(output, null, 2);
|
||||||
if (!output) return;
|
if (!output) return;
|
||||||
this.string = output;
|
this.string = output;
|
||||||
this.compiled = output.compile();
|
let scope = {cat: 1, dog: 2, mouse: 3};
|
||||||
|
this.compiled = output.compile(scope);
|
||||||
|
this.rolled = output.roll(scope);
|
||||||
|
this.reduced = output.reduce(scope);
|
||||||
|
this.reducedJson = JSON.stringify(this.reduced, null, 2)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
2
app/package-lock.json
generated
2
app/package-lock.json
generated
@@ -2805,7 +2805,7 @@
|
|||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
"resolved": false,
|
||||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
||||||
},
|
},
|
||||||
"simpl-schema": {
|
"simpl-schema": {
|
||||||
|
|||||||
Reference in New Issue
Block a user