expression-evaluation
Version:
Expression Evaluation
424 lines (423 loc) • 17.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParserState = void 0;
const ParserFrame_js_1 = require("./ParserFrame.js");
const FunctionDefinition_js_1 = require("./FunctionDefinition.js");
const GlobalFunctions_js_1 = require("./function/GlobalFunctions.js");
const BaseFunctions_js_1 = require("./function/BaseFunctions.js");
const CompositeFunctions_js_1 = require("./function/CompositeFunctions.js");
const MathFunctions_js_1 = require("./function/MathFunctions.js");
const MutationFunctions_js_1 = require("./function/MutationFunctions.js");
const Type_js_1 = require("./Type.js");
class Literal {
value;
constructor(value) {
this.value = value;
}
}
const valueTrue = new Literal(true);
const valueFalse = new Literal(false);
const valueNull = new Literal(undefined);
class Assignment {
operator;
constructor(operator) {
this.operator = operator;
}
}
const funcAssignment = new Assignment();
const funcOrAssignment = new Assignment(GlobalFunctions_js_1.funcOr);
const funcAndAssignment = new Assignment(GlobalFunctions_js_1.funcAnd);
const funcAddAssignment = new Assignment(MathFunctions_js_1.funcAdd);
const funcSubtractAssignment = new Assignment(MathFunctions_js_1.funcSubtract);
const funcMultiplyAssignment = new Assignment(MathFunctions_js_1.funcMultiply);
const funcDivideAssignment = new Assignment(MathFunctions_js_1.funcDivide);
const funcRemainderAssignment = new Assignment(MathFunctions_js_1.funcRemainder);
const symbolParenthesesOpen = Symbol();
const symbolParenthesesClose = Symbol();
const symbolBracketsOpen = Symbol();
const symbolBracketsClose = Symbol();
const symbolBracesOpen = Symbol();
const symbolBracesClose = Symbol();
const symbolColonSeparator = Symbol();
const symbolCommaSeparator = Symbol();
const symbolOptionalType = Symbol();
const symbolScope = Symbol();
const symbolCycle = Symbol();
const isSign = (c) => c === '+' || c === '-';
const isAlpha = (c) => c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c === '_';
const isNumeric = (c) => c >= '0' && c <= '9';
const isAlphanumeric = (c) => isAlpha(c) || isNumeric(c);
const isHexadecimal = (c) => isNumeric(c) || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F';
const isQuotation = (c) => c === '\'' || c === '"' || c === '`';
class ParserState extends ParserFrame_js_1.ParserFrame {
_fragment;
constructor(expr) {
super(expr);
}
get literalValue() {
return this._fragment.value;
}
get assignmentOperator() {
return this._fragment.operator;
}
get operator() {
return this._fragment;
}
get type() {
return this._fragment;
}
get token() {
return this._fragment;
}
get isOperator() {
return this._fragment instanceof FunctionDefinition_js_1.FunctionDefinition;
}
get isLiteral() {
return this._fragment instanceof Literal;
}
get isAssignment() {
return this._fragment instanceof Assignment;
}
get isType() {
return this._fragment instanceof Type_js_1.Type;
}
get isToken() {
return typeof this._fragment === 'string';
}
get isParenthesesOpen() {
return this._fragment === symbolParenthesesOpen;
}
get isParenthesesClose() {
return this._fragment === symbolParenthesesClose;
}
get isBracketsOpen() {
return this._fragment === symbolBracketsOpen;
}
get isBracketsClose() {
return this._fragment === symbolBracketsClose;
}
get isBracesOpen() {
return this._fragment === symbolBracesOpen;
}
get isBracesClose() {
return this._fragment === symbolBracesClose;
}
get isColonSeparator() {
return this._fragment === symbolColonSeparator;
}
get isCommaSeparator() {
return this._fragment === symbolCommaSeparator;
}
get isOptionalType() {
return this._fragment === symbolOptionalType;
}
get isScope() {
return this._fragment === symbolScope;
}
get isCycle() {
return this._fragment === symbolCycle;
}
get isVoid() {
return this._fragment == null;
}
clone() {
const state = new ParserState(this._expr);
state._start = this._start;
state._end = this._end;
state._fragment = this._fragment;
return state;
}
next() {
this._fragment = undefined;
while (this._end < this._expr.length && this._fragment == null) {
this._start = this._end;
const c = this._expr.charAt(this._end);
++this._end;
switch (c) {
case ' ':
case '\t':
case '\n':
case '\r': break;
case '(':
this._fragment = symbolParenthesesOpen;
break;
case ')':
this._fragment = symbolParenthesesClose;
break;
case '[':
this._fragment = symbolBracketsOpen;
break;
case ']':
this._fragment = symbolBracketsClose;
break;
case '{':
this._fragment = symbolBracesOpen;
break;
case '}':
this._fragment = symbolBracesClose;
break;
case ':':
this._fragment = symbolColonSeparator;
break;
case ',':
this._fragment = symbolCommaSeparator;
break;
case '@':
this._fragment = symbolCycle;
break;
case '?':
switch (this._expr.charAt(this._end)) {
case '?':
++this._end;
this._fragment = Type_js_1.typeUnknown;
break;
case ':':
++this._end;
this._fragment = BaseFunctions_js_1.funcCoalesce;
break;
default:
this._fragment = symbolOptionalType;
break;
}
break;
case '$':
this._fragment = BaseFunctions_js_1.funcSwitch;
break;
case '|':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = funcOrAssignment;
break;
default:
this._fragment = GlobalFunctions_js_1.funcOr;
break;
}
break;
case '&':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = funcAndAssignment;
break;
default:
this._fragment = GlobalFunctions_js_1.funcAnd;
break;
}
break;
case '>':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = BaseFunctions_js_1.funcGreaterOrEqual;
break;
default:
this._fragment = BaseFunctions_js_1.funcGreaterThan;
break;
}
break;
case '<':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = BaseFunctions_js_1.funcLessOrEqual;
break;
default:
this._fragment = BaseFunctions_js_1.funcLessThan;
break;
}
break;
case '!':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = BaseFunctions_js_1.funcNotEqual;
break;
default:
this._fragment = GlobalFunctions_js_1.funcNot;
break;
}
break;
case '=':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = BaseFunctions_js_1.funcEqual;
break;
default:
this._fragment = funcAssignment;
break;
}
break;
case '+':
switch (this._expr.charAt(this._end)) {
case '>':
++this._end;
this._fragment = CompositeFunctions_js_1.funcAppend;
break;
case '=':
++this._end;
this._fragment = funcAddAssignment;
break;
default:
this._fragment = MathFunctions_js_1.funcAdd;
break;
}
break;
case '-':
switch (this._expr.charAt(this._end)) {
case '>':
++this._end;
this._fragment = symbolScope;
break;
case '=':
++this._end;
this._fragment = funcSubtractAssignment;
break;
default:
this._fragment = MathFunctions_js_1.funcSubtract;
break;
}
break;
case '*':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = funcMultiplyAssignment;
break;
default:
this._fragment = MathFunctions_js_1.funcMultiply;
break;
}
break;
case '/':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = funcDivideAssignment;
break;
default:
this._fragment = MathFunctions_js_1.funcDivide;
break;
}
break;
case '%':
switch (this._expr.charAt(this._end)) {
case '=':
++this._end;
this._fragment = funcRemainderAssignment;
break;
default:
this._fragment = MathFunctions_js_1.funcRemainder;
break;
}
break;
case '^':
this._fragment = MathFunctions_js_1.funcPower;
break;
case '.':
this._fragment = CompositeFunctions_js_1.funcAt;
break;
case '#':
while (isHexadecimal(this._expr.charAt(this._end))) {
++this._end;
}
this._fragment = new Literal(this._expr.charAt(this._end) === '#'
? (0, MutationFunctions_js_1.parseBuffer)(this._expr.substring(this._start + 1, this._end++))
: parseInt(this._expr.substring(this._start + 1, this._end), 16));
break;
default:
if (isAlpha(c)) {
while (isAlphanumeric(this._expr.charAt(this._end))) {
++this._end;
}
const token = this._expr.substring(this._start, this._end);
switch (token) {
case 'true':
this._fragment = valueTrue;
break;
case 'false':
this._fragment = valueFalse;
break;
case 'null':
this._fragment = valueNull;
break;
case 'void':
this._fragment = Type_js_1.typeVoid;
break;
case 'boolean':
this._fragment = Type_js_1.typeBoolean;
break;
case 'number':
this._fragment = Type_js_1.typeNumber;
break;
case 'buffer':
this._fragment = Type_js_1.typeBuffer;
break;
case 'string':
this._fragment = Type_js_1.typeString;
break;
case 'array':
this._fragment = Type_js_1.typeArray;
break;
case 'object':
this._fragment = Type_js_1.typeObject;
break;
case 'function':
this._fragment = Type_js_1.typeFunction;
break;
default:
this._fragment = token;
break;
}
}
else if (isNumeric(c)) {
while (isNumeric(this._expr.charAt(this._end))) {
++this._end;
}
if (this._expr.charAt(this._end) === '.') {
++this._end;
if (isNumeric(this._expr.charAt(this._end))) {
++this._end;
while (isNumeric(this._expr.charAt(this._end))) {
++this._end;
}
}
else {
--this._end;
}
}
if (this._expr.charAt(this._end) === 'e') {
++this._end;
if (isNumeric(this._expr.charAt(this._end)) || isSign(this._expr.charAt(this._end))) {
++this._end;
while (isNumeric(this._expr.charAt(this._end))) {
++this._end;
}
}
}
this._fragment = new Literal(parseFloat(this._expr.substring(this._start, this._end)));
}
else if (isQuotation(c)) {
while (this._expr.charAt(this._end) !== '' && this._expr.charAt(this._end) !== c) {
++this._end;
}
if (this._end >= this._expr.length) {
this._start = this._expr.length;
throw new Error(`missing closing quotation mark ${c}`);
}
this._fragment = new Literal(this._expr.substring(this._start + 1, this._end++));
}
else {
throw new Error(`unknown symbol ${c}`);
}
break;
}
}
if (this._end > this._expr.length) {
this._start = this._end = this._expr.length;
}
return this;
}
}
exports.ParserState = ParserState;