Skip to content

Commit

Permalink
Add lexer error message provider
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew committed Oct 15, 2024
1 parent b52cb60 commit 2a0cad2
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
4 changes: 3 additions & 1 deletion packages/langium/src/default-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { LangiumParserErrorMessageProvider } from './parser/langium-parser.js';
import { DefaultAsyncParser } from './parser/async-parser.js';
import { DefaultWorkspaceLock } from './workspace/workspace-lock.js';
import { DefaultHydrator } from './serializer/hydrator.js';
import { defaultLexerErrorProvider } from 'chevrotain';

/**
* Context required for creating the default language-specific dependency injection module.
Expand All @@ -61,7 +62,8 @@ export function createDefaultCoreModule(context: DefaultCoreModuleContext): Modu
ValueConverter: () => new DefaultValueConverter(),
TokenBuilder: () => new DefaultTokenBuilder(),
Lexer: (services) => new DefaultLexer(services),
ParserErrorMessageProvider: () => new LangiumParserErrorMessageProvider()
ParserErrorMessageProvider: () => new LangiumParserErrorMessageProvider(),
LexerErrorMessageProvider: () => defaultLexerErrorProvider
},
workspace: {
AstNodeLocator: () => new DefaultAstNodeLocator(),
Expand Down
24 changes: 19 additions & 5 deletions packages/langium/src/parser/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import type { ILexingError, IMultiModeLexerDefinition, IToken, TokenType, TokenTypeDictionary, TokenVocabulary } from 'chevrotain';
import type { ILexerErrorMessageProvider, ILexingError, IMultiModeLexerDefinition, IToken, TokenType, TokenTypeDictionary, TokenVocabulary } from 'chevrotain';
import type { LangiumCoreServices } from '../services.js';
import { Lexer as ChevrotainLexer } from 'chevrotain';
import { Lexer as ChevrotainLexer, defaultLexerErrorProvider } from 'chevrotain';
import type { LexingReport, TokenBuilder } from './token-builder.js';

export abstract class AbstractLexerErrorMessageProvider implements ILexerErrorMessageProvider {

buildUnexpectedCharactersMessage(fullText: string, startOffset: number, length: number, line?: number, column?: number): string {
return defaultLexerErrorProvider.buildUnexpectedCharactersMessage(fullText, startOffset, length, line, column);
}

buildUnableToPopLexerModeMessage(token: IToken): string {
return defaultLexerErrorProvider.buildUnableToPopLexerModeMessage(token);
}
}

export interface LexerResult {
/**
* A list of all tokens that were lexed from the input.
Expand Down Expand Up @@ -40,11 +51,13 @@ export interface Lexer {

export class DefaultLexer implements Lexer {

protected chevrotainLexer: ChevrotainLexer;
protected tokenBuilder: TokenBuilder;
protected readonly tokenBuilder: TokenBuilder;
protected readonly errorMessageProvider: ILexerErrorMessageProvider;
protected tokenTypes: TokenTypeDictionary;
protected chevrotainLexer: ChevrotainLexer;

constructor(services: LangiumCoreServices) {
this.errorMessageProvider = services.parser.LexerErrorMessageProvider;
this.tokenBuilder = services.parser.TokenBuilder;
const tokens = this.tokenBuilder.buildTokens(services.Grammar, {
caseInsensitive: services.LanguageMetaData.caseInsensitive
Expand All @@ -54,7 +67,8 @@ export class DefaultLexer implements Lexer {
const production = services.LanguageMetaData.mode === 'production';
this.chevrotainLexer = new ChevrotainLexer(lexerTokens, {
positionTracking: 'full',
skipValidations: production
skipValidations: production,
errorMessageProvider: this.errorMessageProvider
});
}

Expand Down
3 changes: 2 additions & 1 deletion packages/langium/src/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
******************************************************************************/

// Ensure that all imports are erased at runtime to avoid circular dependencies.
import type { IParserErrorMessageProvider } from 'chevrotain';
import type { IParserErrorMessageProvider, ILexerErrorMessageProvider } from 'chevrotain';
import type { CommentProvider } from './documentation/comment-provider.js';
import type { DocumentationProvider } from './documentation/documentation-provider.js';
import type { Grammar } from './languages/generated/ast.js';
Expand Down Expand Up @@ -60,6 +60,7 @@ export type LangiumDefaultCoreServices = {
readonly ValueConverter: ValueConverter
readonly LangiumParser: LangiumParser
readonly ParserErrorMessageProvider: IParserErrorMessageProvider
readonly LexerErrorMessageProvider: ILexerErrorMessageProvider
readonly CompletionParser: LangiumCompletionParser
readonly TokenBuilder: TokenBuilder
readonly Lexer: Lexer
Expand Down

0 comments on commit 2a0cad2

Please sign in to comment.