import { AndRule, type DataRef, type Rule, type RuleTestResponse, } from '@os-team/lexical-rules'; import { type Parser } from './Parser.js'; import AttTypeParser, { type AttType } from './AttTypeParser.js'; import DefaultDeclParser, { type DefaultDecl } from './DefaultDeclParser.js'; import NameRule from '../rules/NameRule.js'; import SRule from '../rules/SRule.js'; export interface AttDef { name: string; type: AttType; default: DefaultDecl; } /** * See https://www.w3.org/TR/xml/#NT-AttDef */ class AttDefParser implements Parser { private readonly attTypeParser: AttTypeParser; private readonly defaultDeclParser: DefaultDeclParser; private readonly rule: Rule< [undefined, string, undefined, AttType, undefined, DefaultDecl] >; public constructor() { const sRule = new SRule('+'); // S const nameRule = new NameRule(); // Name this.attTypeParser = new AttTypeParser(); // AttType this.defaultDeclParser = new DefaultDeclParser(); // DefaultDecl this.rule = new AndRule([ sRule, nameRule, sRule, this.attTypeParser, sRule, this.defaultDeclParser, ]); // S Name S AttType S DefaultDecl } public test(ref: DataRef, pos: number): RuleTestResponse { const [isValid, nextPos, res] = this.rule.test(ref, pos); if (!isValid || res === undefined) return [false, nextPos]; const [, name, , type, , defaultDecl] = res; return [true, nextPos, { name, type, default: defaultDecl }]; } public build(data: AttDef) { const type = this.attTypeParser.build(data.type); const defaultDecl = this.defaultDeclParser.build(data.default); return ` ${data.name} ${type} ${defaultDecl}`; } } export default AttDefParser;