@scalenc/nc-format
Version:
Library for handling TRUMPF NC file format.
303 lines • 14.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpressionReader = void 0;
const Errors_1 = require("./Errors");
const ParserException_1 = require("./ParserException");
const Expressions = __importStar(require("../models/Expressions"));
const Token_1 = require("./Token");
const Constants_1 = require("./Constants");
const UNARY_OPERATORS = {
[Constants_1.Constants.BITWISE_NOT_OPERATOR]: Expressions.UnaryOperator.B_NOT,
[Constants_1.Constants.LOGICAL_NOT_OPERATOR]: Expressions.UnaryOperator.NOT,
[Constants_1.Constants.MINUS_SIGN]: Expressions.UnaryOperator.NEGATE,
[Constants_1.Constants.CONCAT_OPERATOR]: Expressions.UnaryOperator.TO_STRING,
};
const BINARY_OPERATORS = {
[Constants_1.Constants.MULTIPLY_OPERATOR]: Expressions.BinaryOperator.MULTIPLY,
[Constants_1.Constants.DIVIDE_OPERATOR]: Expressions.BinaryOperator.DIVIDE,
[Constants_1.Constants.ADD_OPERATOR]: Expressions.BinaryOperator.ADD,
[Constants_1.Constants.SUBTRACT_OPERATOR]: Expressions.BinaryOperator.SUBTRACT,
[Constants_1.Constants.CONCAT_OPERATOR]: Expressions.BinaryOperator.CONCAT,
[Constants_1.Constants.EQUAL_OPERATOR]: Expressions.BinaryOperator.EQUAL,
[Constants_1.Constants.INEQUAL_OPERATOR]: Expressions.BinaryOperator.INEQUAL,
[Constants_1.Constants.LESS_OPERATOR]: Expressions.BinaryOperator.LESS,
[Constants_1.Constants.LESS_EQUAL_OPERATOR]: Expressions.BinaryOperator.LESS_EQUAL,
[Constants_1.Constants.GREATER_EQUAL_OPERATOR]: Expressions.BinaryOperator.GREATER_EQUAL,
[Constants_1.Constants.GREATER_OPERATOR]: Expressions.BinaryOperator.GREATER,
[Constants_1.Constants.DIV_OPERATOR]: Expressions.BinaryOperator.DIV_DIVIDE,
[Constants_1.Constants.MOD_OPERATOR]: Expressions.BinaryOperator.MODULO,
[Constants_1.Constants.B_AND_OPERATOR]: Expressions.BinaryOperator.B_AND,
[Constants_1.Constants.B_XOR_OPERATOR]: Expressions.BinaryOperator.B_XOR,
[Constants_1.Constants.B_OR_OPERATOR]: Expressions.BinaryOperator.B_OR,
[Constants_1.Constants.AND_OPERATOR]: Expressions.BinaryOperator.AND,
[Constants_1.Constants.XOR_OPERATOR]: Expressions.BinaryOperator.XOR,
[Constants_1.Constants.OR_OPERATOR]: Expressions.BinaryOperator.OR,
};
class ExpressionReader {
parser;
constructor(parser) {
this.parser = parser;
}
readExpression() {
let operant = this.readOperant();
let binaryOperator = this.tryReadBinaryOperator();
if (binaryOperator !== undefined) {
const stack = [];
for (; binaryOperator !== undefined; binaryOperator = this.tryReadBinaryOperator()) {
while (stack.length > 0 && this.firstHasLowerOrEqualPriority(binaryOperator, stack[stack.length - 1].operator)) {
stack.pop();
}
const binaryOperation = new Expressions.BinaryOperation(binaryOperator, undefined, undefined);
if (stack.length === 0) {
binaryOperation.leftExpression = operant;
operant = binaryOperation;
}
else {
binaryOperation.leftExpression = stack[stack.length - 1].rightExpression;
stack[stack.length - 1].rightExpression = binaryOperation;
}
stack.push(binaryOperation);
binaryOperation.rightExpression = this.readOperant();
}
}
return operant;
}
readOperant() {
const unaryOperator = this.tryReadUnaryOperator();
if (unaryOperator !== undefined) {
const unaryOperation = new Expressions.UnaryOperation(unaryOperator, this.readOperant());
return this.tryMergeNegativeNumber(unaryOperation);
}
this.assertNotLineOrFileEnd();
let expression;
if (this.isNumberToken(this.parser.token)) {
expression = this.readNumber();
}
else if (this.isNameToken(this.parser.token)) {
expression = this.readVariableOrFunction();
}
else if (this.isOpeningBracket(this.parser.token)) {
expression = this.readBracket();
}
else if (this.isString(this.parser.token)) {
expression = this.readString();
}
else {
throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.EXPECTED_OPERANT);
}
return expression;
}
readNumber() {
if (!this.parser.token) {
throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.INVALID_NUMBER);
}
const value = Token_1.tryParseNumber(this.parser.token);
if (value === undefined) {
throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.INVALID_NUMBER);
}
const isInteger = !this.parser.token.value.includes(Constants_1.Constants.DECIMAL_CHAR);
const numberFormat = 'hH'.includes(this.parser.token.value[0])
? Expressions.NumberFormat.HEXADECIMAL
: 'bB'.includes(this.parser.token.value[0])
? Expressions.NumberFormat.BINARY
: Expressions.NumberFormat.DECIMAL;
const number = new Expressions.Number(value, isInteger, numberFormat);
if (this.parser.tryRead() && this.isNumberExponent(this.parser.token)) {
this.parser.tryRead(); // Skip 'EX'.
const exponentSign = this.tryReadSignToken();
this.assertNotLineOrFileEnd();
ParserException_1.ParserException.expected(this.isDecimalNumberToken(this.parser.token), this.parser, Errors_1.Errors.EXPECTED_NUMBER);
const exponent = exponentSign * +this.parser.token.value;
number.value *= Math.pow(10, exponent);
number.isInteger = false;
}
return number;
}
readVariableOrFunction() {
const name = this.parser.token.value;
const expression = this.parser.tryRead() && this.isOpeningBracket(this.parser.token) ? this.readFunction(name) : this.readVariable(name);
return expression;
}
readFunction(name) {
return new Expressions.Function(name, this.readParameterList());
}
readVariable(name) {
if (name.length === 1 &&
this.parser.token &&
!this.parser.token.whiteSpace &&
this.isDecimalNumberToken(this.parser.token) &&
!this.parser.token.value.includes(Constants_1.Constants.DECIMAL_CHAR)) {
name += this.parser.token.value;
this.parser.tryRead();
}
const fieldExpressions = this.parser.token && this.isOpeningFieldBracket(this.parser.token) ? this.readParameterList(true) : undefined;
return new Expressions.Variable(name, fieldExpressions);
}
readParameterList(fieldBrace = false) {
this.parser.tryRead(); // Skip '[' or '('.
const parameters = [];
for (;;) {
this.assertNotLineOrFileEnd();
if (fieldBrace ? this.isClosingFieldBracket(this.parser.token) : this.isClosingBracket(this.parser.token)) {
this.parser.tryRead(); // Skip ']' or ')'.
break;
}
if (this.isArgumentSeparator(this.parser.token)) {
parameters.push(null);
}
else {
parameters.push(this.readExpression());
}
if (this.isArgumentSeparator(this.parser.token)) {
this.parser.tryRead(); // Skip ','.
}
}
return parameters;
}
readBracket() {
this.parser.tryRead(); // Skip '('.
const expression = new Expressions.Bracket(this.readExpression());
this.assertNotLineOrFileEnd();
ParserException_1.ParserException.expected(this.isClosingBracket(this.parser.token), this.parser, Errors_1.Errors.EXPECTED_CLOSING_BRACE);
this.parser.tryRead(); // Skip ')'.
return expression;
}
readString() {
const expression = new Expressions.String(this.parser.token.value);
this.parser.tryRead();
return expression;
}
tryReadBinaryOperator() {
if (!this.isOperatorToken(this.parser.token)) {
return undefined;
}
const binaryOperator = BINARY_OPERATORS[this.parser.token.value.toUpperCase()];
ParserException_1.ParserException.expected(binaryOperator !== undefined, this.parser, Errors_1.Errors.EXPECTED_BINARY_OPERATOR);
this.parser.tryRead();
return binaryOperator;
}
tryReadUnaryOperator() {
if (!this.isOperatorToken(this.parser.token)) {
return undefined;
}
if (this.parser.token.value === Constants_1.Constants.PLUS_SIGN) {
this.parser.tryRead(); // Just skip operator.
return undefined;
}
const unaryOperator = UNARY_OPERATORS[this.parser.token.value.toUpperCase()];
ParserException_1.ParserException.expected(unaryOperator !== undefined, this.parser, Errors_1.Errors.EXPECTED_OPERANT);
this.parser.tryRead();
return unaryOperator;
}
tryMergeNegativeNumber(unaryOperation) {
if (unaryOperation.operator === Expressions.UnaryOperator.NEGATE && unaryOperation.expression instanceof Expressions.Number) {
unaryOperation.expression.value = -unaryOperation.expression.value;
return unaryOperation.expression;
}
return unaryOperation;
}
tryReadSignToken() {
if (!this.isSignToken(this.parser.token)) {
return +1;
}
const sign = this.parser.token.value === Constants_1.Constants.MINUS_SIGN ? -1 : +1;
this.parser.tryRead();
return sign;
}
isLineOrFileEnd(token) {
return !token || token.type === Token_1.TokenType.NEW_LINE || token.type === Token_1.TokenType.COMMENT;
}
isSignToken(token) {
return token?.type === Token_1.TokenType.OPERATOR && (token.value === Constants_1.Constants.PLUS_SIGN || token.value === Constants_1.Constants.MINUS_SIGN);
}
isOperatorToken(token) {
return token?.type === Token_1.TokenType.OPERATOR && !(token.value.length === 1 && token.value[0] === Constants_1.Constants.ASSIGNMENT_OPERATOR);
}
isDecimalNumberToken(token) {
return this.isNumberToken(token) && Constants_1.Constants.DIGIT_CHARS.test(token.value[0]);
}
isNumberToken(token) {
return token?.type === Token_1.TokenType.NUMBER;
}
isNumberExponent(token) {
return token?.type === Token_1.TokenType.IDENTIFIER && !token.whiteSpace && token.value.toUpperCase() === Constants_1.Constants.NUMBER_EXPONENT;
}
isNameToken(token) {
return token?.type === Token_1.TokenType.IDENTIFIER;
}
isOpeningBracket(token) {
return token?.type === Token_1.TokenType.BRACE && token.value.length === 1 && token.value[0] === Constants_1.Constants.OPENING_BRACE;
}
isClosingBracket(token) {
return token?.type === Token_1.TokenType.BRACE && token.value.length === 1 && token.value[0] === Constants_1.Constants.CLOSING_BRACE;
}
isOpeningFieldBracket(token) {
return token?.type === Token_1.TokenType.FIELD_BRACE && token.value.length === 1 && token.value[0] === Constants_1.Constants.OPENING_FIELD_BRACE;
}
isClosingFieldBracket(token) {
return token?.type === Token_1.TokenType.FIELD_BRACE && token.value.length === 1 && token.value[0] === Constants_1.Constants.CLOSING_FIELD_BRACE;
}
isArgumentSeparator(token) {
return token?.type === Token_1.TokenType.SEPARATOR;
}
isString(token) {
return token?.type === Token_1.TokenType.STRING;
}
assertNotLineOrFileEnd() {
ParserException_1.ParserException.assert(!this.isLineOrFileEnd(this.parser.token), this.parser, Errors_1.Errors.UNEXPECTED_LINE_OR_FILE_END);
}
firstHasLowerOrEqualPriority(operation1, operation2) {
const priority1 = this.getPriority(operation1);
const priority2 = this.getPriority(operation2);
return priority1 <= priority2;
}
getPriority(binaryOperator) {
switch (binaryOperator) {
case Expressions.BinaryOperator.MULTIPLY:
case Expressions.BinaryOperator.DIVIDE:
case Expressions.BinaryOperator.DIV_DIVIDE:
case Expressions.BinaryOperator.MODULO:
return 10;
case Expressions.BinaryOperator.ADD:
case Expressions.BinaryOperator.SUBTRACT:
return 9;
case Expressions.BinaryOperator.B_AND:
return 8;
case Expressions.BinaryOperator.B_XOR:
return 7;
case Expressions.BinaryOperator.B_OR:
return 6;
case Expressions.BinaryOperator.AND:
return 5;
case Expressions.BinaryOperator.XOR:
return 4;
case Expressions.BinaryOperator.OR:
return 3;
case Expressions.BinaryOperator.CONCAT:
return 2;
default:
return 1;
}
}
}
exports.ExpressionReader = ExpressionReader;
//# sourceMappingURL=ExpressionReader.js.map