import { AndRule, type DataRef, LiteralRule, RepetitionRule, type Rule, type RuleTestResponse, } from '@os-team/lexical-rules'; import SRule from '../rules/SRule.js'; import type { Parser } from './Parser.js'; import NameRule from '../rules/NameRule.js'; export interface NotationType { type: 'NOTATION'; items: string[]; } /** * The notation attribute type declaration. * See https://www.w3.org/TR/xml/#NT-NotationType */ class NotationTypeParser implements Parser { private readonly rule: Rule< [ string, undefined, string, undefined, string, Array<[undefined, string, undefined, string]>, undefined, string, ] >; public constructor() { const notationRule = new LiteralRule('NOTATION'); // 'NOTATION' const sRule = new SRule('+'); // S const prefixRule = new LiteralRule('('); // '(' const anySRule = new SRule('*'); // S? const nameRule = new NameRule(); // Name const separatorRule = new LiteralRule('|'); // '|' const otherNameRule = new AndRule([ anySRule, separatorRule, anySRule, nameRule, ]); // S? '|' S? Name const anyOtherNameRule = new RepetitionRule(otherNameRule, 0); // (S? '|' S? Name)* const suffixRule = new LiteralRule(')'); // ')' this.rule = new AndRule([ notationRule, sRule, prefixRule, anySRule, nameRule, anyOtherNameRule, anySRule, suffixRule, ]); // 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' } public test(ref: DataRef, pos: number): RuleTestResponse { const [isValid, nextPos, res] = this.rule.test(ref, pos); if (!isValid || res === undefined) return [false, nextPos]; const [, , , , token, rawTokens] = res; return [ true, nextPos, { type: 'NOTATION', items: [token, ...rawTokens.map((item) => item[3])], }, ]; } public build(data: NotationType) { return `NOTATION (${data.items.join('|')})`; } } export default NotationTypeParser;