| import { chevrotain } from '../../../lib.js'; |
| import { MacroLexer } from './MacroLexer.js'; |
|
|
| const { CstParser } = chevrotain; |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| let instance; |
| export { instance as MacroParser }; |
|
|
| class MacroParser extends CstParser { |
| static #instance; |
| static get instance() { return MacroParser.#instance ?? (MacroParser.#instance = new MacroParser()); } |
|
|
| |
| constructor() { |
| super(MacroLexer.def, { |
| traceInitPerf: false, |
| nodeLocationTracking: 'full', |
| recoveryEnabled: true, |
| }); |
| const Tokens = MacroLexer.tokens; |
|
|
| const $ = this; |
|
|
| |
| $.document = $.RULE('document', () => { |
| $.MANY(() => { |
| $.OR([ |
| { ALT: () => $.CONSUME(Tokens.Plaintext, { LABEL: 'plaintext' }) }, |
| { ALT: () => $.CONSUME(Tokens.PlaintextOpenBrace, { LABEL: 'plaintext' }) }, |
| { ALT: () => $.SUBRULE($.macro) }, |
| { ALT: () => $.CONSUME(Tokens.Macro.Start, { LABEL: 'plaintext' }) }, |
| ]); |
| }); |
| }); |
|
|
| |
| $.macro = $.RULE('macro', () => { |
| $.CONSUME(Tokens.Macro.Start); |
| $.OR([ |
| { ALT: () => $.CONSUME(Tokens.Macro.DoubleSlash, { LABEL: 'Macro.identifier' }) }, |
| { ALT: () => $.CONSUME(Tokens.Macro.Identifier, { LABEL: 'Macro.identifier' }) }, |
| ]); |
| $.OPTION(() => $.SUBRULE($.arguments)); |
| $.CONSUME(Tokens.Macro.End); |
| }); |
|
|
| |
| $.arguments = $.RULE('arguments', () => { |
| $.OR([ |
| { |
| ALT: () => { |
| $.CONSUME(Tokens.Args.DoubleColon, { LABEL: 'separator' }); |
| $.AT_LEAST_ONE_SEP({ |
| SEP: Tokens.Args.DoubleColon, |
| DEF: () => $.SUBRULE($.argument, { LABEL: 'argument' }), |
| }); |
| }, |
| }, |
| { |
| ALT: () => { |
| $.OPTION(() => { |
| $.CONSUME(Tokens.Args.Colon, { LABEL: 'separator' }); |
| }); |
| $.SUBRULE($.argumentAllowingColons, { LABEL: 'argument' }); |
| }, |
| |
| |
| |
| IGNORE_AMBIGUITIES: true, |
| }, |
| ]); |
| }); |
|
|
| |
| const validArgumentTokens = [ |
| { ALT: () => $.SUBRULE($.macro) }, |
| { ALT: () => $.CONSUME(Tokens.Identifier) }, |
| { ALT: () => $.CONSUME(Tokens.Unknown) }, |
| { ALT: () => $.CONSUME(Tokens.Args.Colon) }, |
| { ALT: () => $.CONSUME(Tokens.Args.Equals) }, |
| { ALT: () => $.CONSUME(Tokens.Args.Quote) }, |
| ]; |
|
|
| $.argument = $.RULE('argument', () => { |
| $.MANY(() => { |
| $.OR([...validArgumentTokens]); |
| }); |
| }); |
| $.argumentAllowingColons = $.RULE('argumentAllowingColons', () => { |
| $.AT_LEAST_ONE(() => { |
| $.OR([ |
| ...validArgumentTokens, |
| { ALT: () => $.CONSUME(Tokens.Args.DoubleColon) }, |
| ]); |
| }); |
| }); |
|
|
| this.performSelfAnalysis(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| parseDocument(input) { |
| if (!input) { |
| return { cst: null, errors: [{ message: 'Input is empty' }], lexingErrors: [], parserErrors: [] }; |
| } |
|
|
| const lexingResult = MacroLexer.tokenize(input); |
|
|
| this.input = lexingResult.tokens; |
| const cst = this.document(); |
|
|
| const errors = [ |
| ...lexingResult.errors, |
| ...this.errors, |
| ]; |
|
|
| return { cst, errors, lexingErrors: lexingResult.errors, parserErrors: this.errors }; |
| } |
|
|
| test(input) { |
| const lexingResult = MacroLexer.tokenize(input); |
| |
| this.input = lexingResult.tokens; |
| const cst = this.macro(); |
|
|
| |
| |
| const errors = this.errors.map(x => ({ message: x.message, ...x, stack: x.stack })); |
|
|
| return { cst, errors: errors }; |
| } |
| } |
|
|
| instance = MacroParser.instance; |
|
|