@scalenc/nc-format
Version:
Library for handling TRUMPF NC file format.
211 lines • 8.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
const Constants_1 = require("./Constants");
const Errors_1 = require("./Errors");
const ParserException_1 = require("./ParserException");
const Token_1 = require("./Token");
class Parser {
input;
index = 0;
line = 1;
token;
enableLineComments = true;
enableBraceComments = false;
constructor(input) {
this.input = input;
}
get isOk() {
return this.index < this.input.length;
}
get char() {
return this.input[this.index];
}
get isAtLineEnd() {
return this.char === Constants_1.Constants.CARRIAGE_RETURN || this.char === Constants_1.Constants.NEW_LINE;
}
get isNameChar() {
return Constants_1.Constants.NAME_CHARS.test(this.char);
}
get isDigitChar() {
return Constants_1.Constants.DIGIT_CHARS.test(this.char);
}
get isNumberChar() {
return Constants_1.Constants.NUMBER_CHARS.test(this.char);
}
get isNumberConstantChar() {
return this.char === Constants_1.Constants.NUMBER_CONSTANT_SEPARATOR;
}
get isStringChar() {
return this.char === Constants_1.Constants.STRING_SEPARATOR;
}
get isArgumentSeparatorChar() {
return this.char === Constants_1.Constants.ARGUMENT_SEPARATOR;
}
get isBraceChar() {
return this.char === Constants_1.Constants.OPENING_BRACE || this.char === Constants_1.Constants.CLOSING_BRACE;
}
get isColonChar() {
return this.char === Constants_1.Constants.COLON;
}
get isOperatorChar() {
return Constants_1.Constants.OPERATOR_CHARS.includes(this.char);
}
get isFieldBraceChar() {
return this.char === Constants_1.Constants.DEF_FIELD_BEGIN || this.char === Constants_1.Constants.DEF_FIELD_END;
}
assertNotLineOrFileEnd() {
ParserException_1.ParserException.assert(!Token_1.isLineOrFileEnd(this.token), this, Errors_1.Errors.UNEXPECTED_LINE_OR_FILE_END);
}
readIntegerNumber() {
const value = Token_1.tryGetNumberAsInteger(this.token);
if (value === undefined) {
throw new ParserException_1.ParserException(this, Errors_1.Errors.EXPECTED_INTEGER);
}
this.tryRead();
return value;
}
tryRead() {
const whiteSpace = this.trySkipWhiteSpace();
if (!this.isOk) {
this.token = undefined;
}
else if (this.isAtLineEnd) {
this.token = { type: Token_1.TokenType.NEW_LINE, whiteSpace, value: this.readSingle() };
}
else if (this.enableLineComments && this.char === Constants_1.Constants.COMMENT_CHAR) {
this.token = { type: Token_1.TokenType.COMMENT, whiteSpace, value: this.readComment() };
}
else if (this.enableBraceComments && this.char === Constants_1.Constants.OPENING_BRACE) {
this.token = { type: Token_1.TokenType.COMMENT, whiteSpace, value: this.readBraceComment() };
}
else if (this.isNameChar) {
this.token = this.correctTokenTypeForNamedOperators({ type: Token_1.TokenType.IDENTIFIER, whiteSpace, value: this.readName() });
}
else if (this.isNumberConstantChar) {
this.token = { type: Token_1.TokenType.NUMBER, whiteSpace, value: this.readNumberConstant() };
}
else if (this.isNumberChar) {
this.token = { type: Token_1.TokenType.NUMBER, whiteSpace, value: this.readNumber() };
}
else if (this.isStringChar) {
this.token = { type: Token_1.TokenType.STRING, whiteSpace, value: this.readString() };
}
else if (this.isArgumentSeparatorChar) {
this.token = { type: Token_1.TokenType.SEPARATOR, whiteSpace, value: this.readSingle() };
}
else if (this.isColonChar) {
this.token = { type: Token_1.TokenType.COLON, whiteSpace, value: this.readSingle() };
}
else if (this.isBraceChar) {
this.token = { type: Token_1.TokenType.BRACE, whiteSpace, value: this.readSingle() };
}
else if (this.isOperatorChar) {
this.token = { type: Token_1.TokenType.OPERATOR, whiteSpace, value: this.readOperator() };
}
else if (this.isFieldBraceChar) {
this.token = { type: Token_1.TokenType.FIELD_BRACE, whiteSpace, value: this.readSingle() };
}
else {
throw new ParserException_1.ParserException(this, Errors_1.Errors.INVALID_CHARACTER.replace(/\{0\}/g, this.char));
}
return !!this.token;
}
readComment() {
return this.readWhile(() => !this.isAtLineEnd, 1);
}
readBraceComment() {
const comment = this.readWhile(() => !this.isAtLineEnd && this.char != Constants_1.Constants.CLOSING_BRACE, 1);
if (this.char === Constants_1.Constants.CLOSING_BRACE) {
this.tryReadNextChar(); // Skip end of comment.
this.trySkipWhiteSpace();
ParserException_1.ParserException.assert(this.isAtLineEnd, this, Errors_1.Errors.ADDTIONAL_CHARS_AFTER_BRACE_COMMENT);
}
return comment;
}
readName() {
const i = this.index;
return this.readWhile(() => this.isNameChar || (this.isDigitChar && !this.isSpecialName(i)));
}
isSpecialName(startIndex) {
return (
// One-character names with subsequent digit are assignments, e.g. 'N100'.
this.index - startIndex === 1 ||
// 'EX' with subsequent digit are exponents for numbers, e.g. '1EX3'.
(this.index - startIndex === 2 && this.input.substring(startIndex, this.index).toUpperCase() === Constants_1.Constants.NUMBER_EXPONENT));
}
readNumber() {
let hasDot = this.char === '.';
return this.readWhile(() => {
if (this.char === '.') {
ParserException_1.ParserException.assert(!hasDot, this, Errors_1.Errors.TOO_MANY_DECIMAL_CHARS);
hasDot = true;
}
return this.isNumberChar;
});
}
readNumberConstant() {
const content = this.readWhile(() => !this.isAtLineEnd && !this.isNumberConstantChar, 1);
ParserException_1.ParserException.assert(this.isOk && this.isNumberConstantChar, this, Errors_1.Errors.MISSING_STRING_END);
this.tryReadNextChar(); // Skip end of number constant.
return content;
}
readString() {
const content = this.readWhile(() => !this.isAtLineEnd && !this.isStringChar, 1);
ParserException_1.ParserException.assert(this.isOk && this.isStringChar, this, Errors_1.Errors.MISSING_STRING_END);
this.tryReadNextChar(); // Skip end of string.
return content;
}
readOperator() {
let s = this.readSingle();
while (this.isOk && this.isOperatorChar && this.isValidOperator(s + this.char)) {
s += this.char;
this.tryReadNextChar();
}
return s;
}
isValidOperator(s) {
if (s.length === 2) {
if (s[0] === Constants_1.Constants.LESS_OPERATOR_CHAR) {
return s[1] === Constants_1.Constants.LESS_OPERATOR_CHAR || s[1] === Constants_1.Constants.EQUAL_OPERATOR_CHAR || s[1] === Constants_1.Constants.GREATER_OPERATOR_CHAR;
}
return (s[0] === Constants_1.Constants.GREATER_OPERATOR_CHAR || s[0] === Constants_1.Constants.EQUAL_OPERATOR_CHAR) && s[1] === Constants_1.Constants.EQUAL_OPERATOR_CHAR;
}
return s.length === 1;
}
trySkipWhiteSpace() {
const isWhiteSpace = () => !this.isAtLineEnd && Constants_1.Constants.WHITE_SPACE_CHARS.test(this.char);
return isWhiteSpace() ? this.readWhile(isWhiteSpace) : '';
}
correctTokenTypeForNamedOperators(token) {
if (Constants_1.Constants.NAMED_OPERATORS.includes(token.value.toUpperCase())) {
token.type = Token_1.TokenType.OPERATOR;
}
return token;
}
readSingle() {
const c = this.char;
this.tryReadNextChar();
return c;
}
readWhile(predicate, skipFirst = 0) {
const i = this.index + skipFirst;
// eslint-disable-next-line no-empty
while (this.tryReadNextChar() && predicate()) { }
return this.input.substring(i, this.index);
}
tryReadNextChar() {
if (this.isOk) {
++this.index;
if (this.isAtLineEnd) {
++this.line;
if (this.char === Constants_1.Constants.CARRIAGE_RETURN && this.input[this.index + 1] === Constants_1.Constants.NEW_LINE) {
++this.index;
}
}
}
return this.isOk;
}
}
exports.Parser = Parser;
//# sourceMappingURL=Parser.js.map