Separated parser class nodes and began writing compile methods

This commit is contained in:
Thaum Rystra
2019-04-06 10:56:53 +02:00
parent d21827106c
commit b7b0ac9c00
14 changed files with 167 additions and 207 deletions

View File

@@ -0,0 +1 @@
//TODO

View File

@@ -0,0 +1,21 @@
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
export default class ConstantNode extends ParseNode {
constructor({value, type, errors}){
super();
// string, number, boolean, numberArray, uncompiledNode
this.type = type;
this.value = value;
if (errors) this.errors = errors;
}
compile(){
return this;
}
reduce(){
if (this.type === 'numberArray'){
return this.value.reduce((total, num) => total + num, 0);
} else {
return this;
}
}
}

View File

@@ -0,0 +1,40 @@
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
export default class IfNode extends ParseNode {
constructor({condition, consequent, alternative}){
super();
this.condition = condition;
this.consequent = consequent;
this.alternative = alternative;
}
compile(){
let condition = this.condition.compile();
let consequent = this.consequent.compile();
let alternative = this.alternative.compile();
if (
condition.type !== 'string' &&
condition.type !== 'number' &&
condition.type !== 'boolean'
){
// Handle unresolved condition
return new ConstantNode({
value: `if (${condition.value}) ${consequent.value} else ${alternative.value}`,
type: 'uncompiledNode',
errors: [
...condition.errors,
...consequent.errors,
...alternative.errors,
],
});
} else {
// So long as the condition reolves, return the correct alternative,
// even if it's unresolved
if (condition.value){
return consequent;
} else {
return alternative;
}
}
}
}

View File

@@ -0,0 +1,11 @@
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
export default class OperatorNode extends ParseNode {
constructor({left, right, operator, fn}) {
super();
this.left = left;
this.right = right;
this.fn = fn;
this.operator = operator;
}
}

View File

@@ -0,0 +1,14 @@
export default class ParseNode {
// Compiling a node must return a ConstantNode
compile(){
throw new Meteor.Error('Compile not implemented on ' + this);
}
// Compile, but turn rolls into arrays
roll(){
return this.compile();
}
// Compile, turn rolls into arrays, and reduce those arrays into single values
reduce(){
return this.compileAndRoll()
}
}

View File

View File

@@ -0,0 +1,24 @@
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
export default class SymbolNode extends ParseNode {
constructor({name}){
super();
this.name = name;
}
compile(scope){
let value = scope && scope[this.name];
let type = typeof value;
if (type === 'string' || type === 'number' || type === 'boolean'){
return new ConstantNode({value, type});
} else if (type === 'undefined'){
return new ConstantNode({
value: this.name,
type: 'uncompiledNode',
errors: [`${this.name} could not be resolved`]
});
} else {
throw new Meteor.Error(`Unexpected case: ${this.name} resolved to ${value}`);
}
}
}