Skip to content

Commit 35ce326

Browse files
authored
Fix unassigned data type rule usage (#1367)
1 parent 1f5d124 commit 35ce326

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

packages/langium/src/parser/langium-parser.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,15 @@ export class LangiumParser extends AbstractLangiumParser {
233233
if (assignment) {
234234
this.assign(assignment.operator, assignment.feature, result, cstNode, isCrossRef);
235235
} else if (!assignment) {
236-
// If we call a subrule without an assignment
237-
// We either append the result of the subrule (data type rule)
238-
// Or override the current object with the newly parsed object
236+
// If we call a subrule without an assignment we either:
237+
// 1. append the result of the subrule (data type rule)
238+
// 2. override the current object with the newly parsed object
239+
// If the current element is an AST node and the result of the subrule
240+
// is a data type rule, we can safely discard the results.
239241
const current = this.current;
240242
if (isDataTypeNode(current)) {
241243
current.value += result.toString();
242-
} else {
244+
} else if (typeof result === 'object' && result) {
243245
const resultKind = result.$type;
244246
const object = this.assignWithoutOverride(result, current);
245247
if (resultKind) {

packages/langium/test/parser/langium-parser-builder.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { AstNode, CstNode, GenericAstNode, Grammar, GrammarAST, LangiumPars
99
import { EmptyFileSystem, DefaultTokenBuilder } from 'langium';
1010
import { describe, expect, test, onTestFailed, beforeEach } from 'vitest';
1111
import { createLangiumGrammarServices, createServicesForGrammar } from 'langium/grammar';
12+
import { expandToString } from 'langium/generate';
1213
import { parseHelper } from 'langium/test';
1314
import { EOF } from 'chevrotain';
1415

@@ -826,6 +827,34 @@ describe('Handling EOF', () => {
826827
}
827828
});
828829

830+
describe('Unassigned data type rules', () => {
831+
832+
test('Can successfully parse unassigned data type rule in parser rule', async () => {
833+
const parser = await parserFromGrammar(expandToString`
834+
grammar HelloWorld
835+
836+
entry Model:
837+
((persons+=Person) EOL)*;
838+
839+
Person:
840+
'person' name=ID;
841+
842+
hidden terminal WS: /[ \\t]+/;
843+
terminal ID: /[_a-zA-Z][\\w_]*/;
844+
terminal NEWLINE: /\\r?\\n/;
845+
EOL returns string:
846+
NEWLINE | EOF;`
847+
);
848+
const parseResult = parser.parse(expandToString`
849+
person John
850+
person Jane
851+
`);
852+
expect(parseResult.lexerErrors).toHaveLength(0);
853+
expect(parseResult.parserErrors).toHaveLength(0);
854+
});
855+
856+
});
857+
829858
async function parserFromGrammar(grammar: string): Promise<LangiumParser> {
830859
return (await createServicesForGrammar({ grammar })).parser.LangiumParser;
831860
}

0 commit comments

Comments
 (0)