UNPKG

@scalenc/nc-format

Version:

Library for handling TRUMPF NC file format.

233 lines 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StatementReader = void 0; const Expressions_1 = require("../models/Expressions"); const Assignment_1 = require("../models/Statements/Assignment"); const FlowControlInstruction_1 = require("../models/Statements/FlowControlInstruction"); const GCode_1 = require("../models/Statements/GCode"); const Goto_1 = require("../models/Statements/Goto"); const Instruction_1 = require("../models/Statements/Instruction"); const MCode_1 = require("../models/Statements/MCode"); const Constants_1 = require("./Constants"); const DeclarationReader_1 = require("./DeclarationReader"); const Errors_1 = require("./Errors"); const ExpressionReader_1 = require("./ExpressionReader"); const ParserException_1 = require("./ParserException"); const Token_1 = require("./Token"); class StatementReader { parser; expressionReader; enableGCodeArguments = false; enableStringInstructions = false; constructor(parser) { this.parser = parser; this.expressionReader = new ExpressionReader_1.ExpressionReader(parser); } read() { const statement = this.tryRead(); if (!statement) { throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.UNEXPECTED_LINE_OR_FILE_END); } return statement; } tryRead() { if (Token_1.isLineOrFileEnd(this.parser.token)) { return undefined; } if (Token_1.isGCode(this.parser.token)) { return this.readGCode(); } else if (Token_1.isMCode(this.parser.token)) { return this.readMCode(); } else if (Token_1.isGoto(this.parser.token)) { return this.readGoto(); } else if (Token_1.isDeclaration(this.parser.token)) { return this.readDeclaration(); } else if (Token_1.isFlowControlInstruction(this.parser.token)) { return this.readFlowControlInstruction(); } else { return this.readAssignmentOrInstruction(); } } readGCode() { this.parser.tryRead(); // Skip 'G'. this.parser.assertNotLineOrFileEnd(); const id = this.parser.readIntegerNumber(); const args = this.enableGCodeArguments && Token_1.isOpeningFieldBrace(this.parser.token) ? this.readFieldBraceArguments() : undefined; return new GCode_1.GCode(id, args); } readFieldBraceArguments() { const args = []; while (this.parser.tryRead()) { // Skip '[', or ',' this.parser.assertNotLineOrFileEnd(); args.push(this.expressionReader.readExpression()); if (this.parser.token?.type !== Token_1.TokenType.SEPARATOR) { break; } } ParserException_1.ParserException.assert(Token_1.isCloseingFieldBrace(this.parser.token), this.parser, Errors_1.Errors.EXPECTED_CLOSING_FIELD_BRACE); this.parser.tryRead(); // Skip ']'. return args; } readMCode() { this.parser.tryRead(); // Skip 'M'. this.parser.assertNotLineOrFileEnd(); return new MCode_1.MCode(this.parser.readIntegerNumber()); } readGoto() { let direction = Goto_1.GotoDirection.SEARCH; if (this.parser.token && this.parser.token.value.length !== Constants_1.Constants.GOTO.length) { switch (this.parser.token.value[Constants_1.Constants.GOTO.length].toUpperCase()) { case Constants_1.Constants.GOTO_START: direction = Goto_1.GotoDirection.START; break; case Constants_1.Constants.GOTO_BACKWARD: direction = Goto_1.GotoDirection.BACKWARD; break; case Constants_1.Constants.GOTO_FORWARD: direction = Goto_1.GotoDirection.FORWARD; break; case Constants_1.Constants.GOTO_SEARCH_NO_ERRORS: direction = Goto_1.GotoDirection.SEARCH_WITHOUT_ERROR; break; default: ParserException_1.ParserException.fail(this.parser, Errors_1.Errors.EXPECTED_GOTO); break; } } this.parser.tryRead(); let target = undefined; if (direction !== Goto_1.GotoDirection.START) { this.parser.assertNotLineOrFileEnd(); target = this.expressionReader.readExpression(); } return new Goto_1.Goto(direction, target); } readDeclaration() { const declarationReader = new DeclarationReader_1.DeclarationReader(this.parser); return declarationReader.readDeclaration(); } readFlowControlInstruction() { const name = this.parser.token?.value.toUpperCase(); this.parser.tryRead(); // Skip instruction keyword. let type; let expressions; switch (name) { case Constants_1.Constants.IF: type = FlowControlInstruction_1.FlowControlInstructionType.IF; expressions = [this.expressionReader.readExpression()]; break; case Constants_1.Constants.ELSE: type = FlowControlInstruction_1.FlowControlInstructionType.ELSE; break; case Constants_1.Constants.ENDIF: type = FlowControlInstruction_1.FlowControlInstructionType.ENDIF; break; case Constants_1.Constants.WHILE: type = FlowControlInstruction_1.FlowControlInstructionType.WHILE; expressions = [this.expressionReader.readExpression()]; break; case Constants_1.Constants.ENDWHILE: type = FlowControlInstruction_1.FlowControlInstructionType.ENDWHILE; break; case Constants_1.Constants.REPEAT: type = FlowControlInstruction_1.FlowControlInstructionType.REPEAT; break; case Constants_1.Constants.UNTIL: type = FlowControlInstruction_1.FlowControlInstructionType.UNTIL; expressions = [this.expressionReader.readExpression()]; break; case Constants_1.Constants.LOOP: type = FlowControlInstruction_1.FlowControlInstructionType.LOOP; break; case Constants_1.Constants.ENDLOOP: type = FlowControlInstruction_1.FlowControlInstructionType.ENDLOOP; break; case Constants_1.Constants.FOR: { type = FlowControlInstruction_1.FlowControlInstructionType.FOR; const assignment = this.readAssignmentOrInstruction(); if (!(assignment instanceof Assignment_1.Assignment)) { throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.EXPECTED_ASSIGNMENT_BUT_INSTRUCTION); } if (!Token_1.isToKeyword(this.parser.token)) { throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.EXPECTED_TO_KEYWORD); } this.parser.tryRead(); // Skip 'TO'. const expression = this.expressionReader.readExpression(); expressions = [new Expressions_1.Variable(assignment.variable), assignment.expression, expression]; break; } case Constants_1.Constants.ENDFOR: type = FlowControlInstruction_1.FlowControlInstructionType.ENDFOR; break; default: throw new Error(`Expected flow control instruction but found ${name}`); } return new FlowControlInstruction_1.FlowControlInstruction(type, expressions); } readAssignmentOrInstruction() { const expression = this.expressionReader.readExpression(); if (expression instanceof Expressions_1.Variable) { if (Token_1.isAssignmentOperator(this.parser.token)) { return this.readExplicitAssignment(expression); } if (expression.fieldExpressions) { throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.UNEXPECTED_FIELD_BRACES); } if (expression.name.length === 1) { return this.readInlineAssignment(expression.name); } if (Constants_1.Constants.DIGIT_CHARS.test(expression.name[1])) { return this.splitInlineAssignment(expression.name); } return new Instruction_1.Instruction(expression.name); } if (expression instanceof Expressions_1.Function) { return new Instruction_1.Instruction(expression.name, expression.args); } if (expression instanceof Expressions_1.BinaryOperation) { return this.extractInlineAssignmentWithSign(expression); } if (this.enableStringInstructions && expression instanceof Expressions_1.String) { return new Instruction_1.Instruction(`${Constants_1.Constants.STRING_SEPARATOR}${expression.value}${Constants_1.Constants.STRING_SEPARATOR}`); } throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.EXPECTED_ASSIGNMENT_OR_INSTRUCTION_BUT_FOUND_EXPRESSION); } readExplicitAssignment(variable) { this.parser.tryRead(); // Skip '='. const expression = this.expressionReader.readExpression(); return new Assignment_1.Assignment(variable.name, variable.fieldExpressions, expression); } readInlineAssignment(name) { const expression = this.expressionReader.readExpression(); return new Assignment_1.Assignment(name, undefined, expression); } splitInlineAssignment(name) { return new Assignment_1.Assignment(name.substring(0, 1), undefined, new Expressions_1.Number(+name.substring(1), true)); } extractInlineAssignmentWithSign(binaryOperation) { // Note, there might be more complicated expressions which are not supported by this algorithm, // e.g. X-1.2+3 which should read as X = -1.2+3, but is {{X - 1.2} + 3}. Thus, the left expression // is no number but a binary '-' operation. if (binaryOperation.operator === Expressions_1.BinaryOperator.ADD || binaryOperation.operator === Expressions_1.BinaryOperator.SUBTRACT) { if (binaryOperation.leftExpression instanceof Expressions_1.Variable && !binaryOperation.leftExpression.fieldExpressions && binaryOperation.leftExpression.name.length === 1) { if (binaryOperation.operator === Expressions_1.BinaryOperator.SUBTRACT) { if (binaryOperation.rightExpression instanceof Expressions_1.Number) { binaryOperation.rightExpression.value = -binaryOperation.rightExpression.value; } } return new Assignment_1.Assignment(binaryOperation.leftExpression.name, undefined, binaryOperation.rightExpression); } } throw new ParserException_1.ParserException(this.parser, Errors_1.Errors.EXPECTED_ASSIGNMENT_OR_INSTRUCTION_BUT_FOUND_EXPRESSION); } } exports.StatementReader = StatementReader; //# sourceMappingURL=StatementReader.js.map