fix(linuxcnc): support named O-word labels and subroutine return values - #158
Merged
Merged
Conversation
- lex named O-word labels (o<name>) as OSUB, flagging unterminated labels - parse and format optional return values on return [expr] and endsub [expr] - carry return-value expressions through the AST and AstTraverser - match O-word labels case-insensitively per LinuxCNC input rules - preserve the source case of named O-word labels when formatting - add UNTERMINATED_O_LABEL diagnostic and suggestion - regression-test the tool-change macro fixture parses with no diagnostics
misiekhardcore
commented
Sep 21, 2026
Comment on lines
+131
to
+133
| * Normalize an O-block label for output. Numeric labels are upper-cased | ||
| * (o100 -> O100); named labels (o<name>) keep their source case because | ||
| * LinuxCNC named subroutines conventionally use lower case. |
Contributor
Author
There was a problem hiding this comment.
named 0 blocks can also be uppercased, we dont need this special handling
misiekhardcore
force-pushed
the
forge/ws-3fa904df
branch
from
September 21, 2026 20:22
de7bac9 to
ed963f5
Compare
- lex o<name> labels as OSUB (with unterminated diagnostics) - parse and format optional return [expr] / endsub [expr] - match O-word labels case-insensitively per LinuxCNC input rules - carry return-value expressions through the AST and traverser - preserve named label case in the formatter - add UNTERMINATED_O_LABEL diagnostic and suggestion - regression-test tool-change-macro.ngc parses with no diagnostics
misiekhardcore
force-pushed
the
forge/ws-3fa904df
branch
from
September 21, 2026 20:34
ed963f5 to
4e83151
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix for LinuxCNC named O-word labels and subroutine return values
What was fixed
This PR fixes a long-standing bug where valid LinuxCNC macro files using named O-word labels (
o<name> sub / call / endsub) and return values (return [expr]/endsub [expr]) were incorrectly reported with syntax errors like "Unexpected token".Changes made
Lexer (
src/lexer/GCodeScanner.ts)scanNamedOWord()to tokenizeo<name>as a single OSUB token, flagging unterminated labels (missing closing>).O100) remain unchanged.AST & Factory (
src/parser/nodes/,src/parser/AstFactory.ts)ReturnStatementNodeandSubroutineDefinitionNodewith an optionalreturnValue?: ExpressionNodefield to store bracketed expressions after the keyword.Parser (
src/parser/dialects/LinuxCNCParser.ts,src/parser/BaseParser.ts)parseOptionalBracketedExpression()to consume[expr]afterRETURNorENDSUB.parseReturn()andparseSubroutineDefinition()to handle return values.labelsMatch(token, label)helper that normalizes labels (trim().toUpperCase()) while preserving the source text in AST nodes.Traversal (
src/parser/AstTraverser.ts)returnValuein both RETURN and ENDSUB contexts (before their respective end callbacks).Formatter (
src/formatter/dialects/LinuxCNCFormatter.ts)formatLabel()to preserve the source case of named O-word labels instead of uppercasing them.[value]after RETURN/ENDSUB lines informatReturnStatementLine()andformatSubroutineDefinitionClose().Diagnostics (
src/providers/ErrorSuggestionDatabase.ts)UNTERMINATED_O_LABELwith an appropriate suggestion message for malformed labels likeo<name.Tests added / modified (TDD approach)
All tests were written first and failed before implementing the corresponding code:
src/test/GCodeLexer.test.tsscanNamedOWord()src/parser/AstFactory.test.ts(implied)src/test/SubroutineParsing.test.tsreturn [expr]/endsub [expr], label matching, unterminated diagnosticssrc/test/formatters/LinuxCNCFormatter.test.tssrc/test/AstTraverser.test.tssrc/test/FixtureParsing.test.ts(NEW)tool-change-macro.ngcfixture with zero ErrorNodesValidation results (all green)
Files changed (17 files, ~+455 / -18 lines)
CHANGELOG.md–[Unreleased]updated with Added/Fixed entriessrc/lexer/GCodeScanner.ts– newscanNamedOWord()+ unterminated handlingsrc/parser/AstFactory.ts– return value fields, range updatessrc/parser/BaseParser.ts– case-insensitive label matching helpersrc/parser/dialects/LinuxCNCParser.ts– parseOptionalBracketedExpression(), labelsMatch()src/parser/nodes/ErrorNode.ts– new UNTERMINATED_O_LABEL error codesrc/parser/nodes/ReturnStatementNode.ts, SubroutineDefinitionNode.ts– optional return valuesrc/parser/AstTraverser.ts– traverse return-value expressionssrc/formatter/dialects/LinuxCNCFormatter.ts– preserve named label case, emit valuessrc/providers/ErrorSuggestionDatabase.ts– new diagnostic suggestionsrc/test/fixtures/tool-change-macro.ngc)Notes on variable diagnostics
The file still shows 26 hint-level semantic diagnostics (e.g., "Variable '#<selected_tool>' is used but never assigned in this file"). These are pre-existing hints from the
SemanticAnalyzerthat help users debug their macros by showing which controller variables they've defined but never use. They are informational, not errors or warnings.Backward compatibility
AC checklist: All acceptance criteria from Phase 1 are met. The real-world macro
tool-change-macro.ngcnow parses cleanly with zero syntax errors.