UNPKG

@neo4j-cypher/language-support

Version:
76 lines (65 loc) 2.73 kB
import { CharStreams, CommonTokenStream } from 'antlr4'; import CypherLexer from '../generated-parser/CypherCmdLexer'; import CypherParser from '../generated-parser/CypherCmdParser'; import { getTokens } from '../helpers'; import { CypherTokenType, lexerSymbols, tokenNames } from '../lexerSymbols'; describe('Lexer tokens', () => { test('List of tokens should match generated parser symbolic names', () => { // Read in auto-generated symbolic names from the parser and remove special characters const symbolicNames = CypherLexer.symbolicNames; // Lexer keyword list which we want to keep up-to-date // Note that it is numeric so we need to map to it's corresponding symbolicName const lexerKeywords = Object.keys(lexerSymbols).map((k) => { const symbolNumber = parseInt(k, 10); // There is no "-1" position in the symbolic name list so we handle EOF separately if (symbolNumber === CypherParser.EOF) { return 'EOF'; } return symbolicNames[symbolNumber]; }); // Check for keywords that exist in the parser but not the lexer const addedKeywords = symbolicNames.filter( (x) => x !== null && !lexerKeywords.includes(x), ); expect(addedKeywords).toHaveLength(0); // Check for keywords that exist in the lexer but not the parser // With the current setup this should not happen const deletedKeywords = lexerKeywords.filter( (x) => x !== 'EOF' && !symbolicNames.includes(x), ); expect(deletedKeywords).toHaveLength(0); }); test('Names of lexer keywords can be lexed back into the token', () => { const keywordTokens = Object.entries(lexerSymbols) .filter(([, v]) => v === CypherTokenType.keyword) .map(([k]) => parseInt(k, 10)); keywordTokens.forEach((token) => { const tokenName = tokenNames[token]; const inputStream = CharStreams.fromString(tokenName); const lexer = new CypherLexer(inputStream); const tokenStream = new CommonTokenStream(lexer); tokenStream.fill(); const tokens = getTokens(tokenStream); expect(tokens.length).toBe(2); // If the test fails, it is useful to see the token that was parsed if (tokens[0].type !== token) { console.error( 'unexpected token', tokenName, token, 'symbolic name', CypherLexer.symbolicNames[token], ); console.error( 'expected token', tokenNames[tokens[0].type], tokens[0].type, 'symbolic name', CypherLexer.symbolicNames[tokens[0].type], ); } expect(tokens[0].type).toBe(token); expect(tokens[1].type).toBe(CypherLexer.EOF); }); }); });