UNPKG

@bablr/language-en-cstml

Version:
389 lines 14.1 kB
/* @macrome * @generatedby @bablr/macrome-generator-bablr * @generatedfrom ./grammar.macro.js#079201c0d77e63f01a340d46cca7d0e5df3095e4 * This file is autogenerated. Please do not edit it directly. * When editing run `npx macrome watch` then change the file this is generated from. */ import _applyDecs from "@babel/runtime/helpers/applyDecs2305"; let _initProto, _DoctypeTagDecs, _ReferenceTagDecs, _BindingTagDecs, _GapTagDecs, _ShiftTagDecs, _NullTagDecs, _InitializerTagDecs, _AttributeDefinitionDecs, _NodeDecs, _PropertyDecs, _OpenNodeTagDecs, _CloseNodeTagDecs, _LiteralTagDecs, _PunctuatorDecs, _KeywordDecs, _AnyDecs; import { re, spam as m } from '@bablr/helpers/shorthand'; import { Node, CoveredBy, InjectFrom, Attributes, UndefinedAttributes, AllowEmpty, Literal } from '@bablr/helpers/decorators'; import { o, eat, eatMatch, match, defineAttribute, fail } from '@bablr/helpers/grammar'; import { buildString } from '@bablr/helpers/builders'; import * as productions from '@bablr/helpers/productions'; import * as Space from '@bablr/language-en-blank-space'; import * as JSON from '@bablr/language-en-cstml-json'; export const canonicalURL = 'https://bablr.org/languages/core/en/cstml'; export const dependencies = { Space, JSON }; export const defaultMatcher = m`<Node />`; const escapables = new Map(Object.entries({ n: '\n', r: '\r', t: '\t', 0: '\0' })); function first(iter) { for (let value of iter) return value; } export function* eatMatchTrivia() { if (yield match(re`/[ \t\r\n]/`)) { return yield eat(m`#: :Space: <__Blank />`); } return null; } export const grammar = class CSTMLGrammar { static { [_initProto] = _applyDecs(this, [[Node, 2, "Document"], [_DoctypeTagDecs, 2, "DoctypeTag"], [_ReferenceTagDecs, 2, "ReferenceTag"], [[AllowEmpty, Node], 2, "ReferenceFlags"], [_BindingTagDecs, 2, "BindingTag"], [_GapTagDecs, 2, "GapTag"], [_ShiftTagDecs, 2, "ShiftTag"], [_NullTagDecs, 2, "NullTag"], [_InitializerTagDecs, 2, "InitializerTag"], [_AttributeDefinitionDecs, 2, "AttributeDefinition"], [_NodeDecs, 2, "Node"], [_PropertyDecs, 2, "Property"], [[Node, AllowEmpty], 2, "NodeFlags"], [_OpenNodeTagDecs, 2, "OpenNodeTag"], [_CloseNodeTagDecs, 2, "CloseNodeTag"], [Node, 2, "IdentifierPath"], [Node, 2, "Identifier"], [Node, 2, "IdentifierContent"], [_LiteralTagDecs, 2, "LiteralTag"], [_PunctuatorDecs, 2, "Punctuator"], [Node, 2, "EscapeSequence"], [Node, 2, "EscapeCode"], [_KeywordDecs, 2, "Keyword"], [_AnyDecs, 2, "Any"]], []).e; } constructor() { _initProto(this); } *[(_DoctypeTagDecs = [CoveredBy('Tag'), CoveredBy('Expression'), Node], _ReferenceTagDecs = [Node, CoveredBy('Tag'), CoveredBy('Expression')], _BindingTagDecs = [Node, CoveredBy('Tag')], _GapTagDecs = [Node, CoveredBy('Tag'), CoveredBy('Expression'), CoveredBy('PropertyValue')], _ShiftTagDecs = [Node, CoveredBy('Tag')], _NullTagDecs = [Node, CoveredBy('Tag'), CoveredBy('Expression'), CoveredBy('PropertyValue')], _InitializerTagDecs = [UndefinedAttributes(['isArray']), Node, CoveredBy('Tag'), CoveredBy('PropertyValue')], _AttributeDefinitionDecs = [Node, CoveredBy('Tag')], _NodeDecs = [Node, CoveredBy('PropertyValue')], _PropertyDecs = [Node, CoveredBy('NodeChild')], _OpenNodeTagDecs = [UndefinedAttributes(['balanced', 'balancedSpan']), Node, CoveredBy('Tag')], _CloseNodeTagDecs = [Attributes({ balancer: true }), Node, CoveredBy('Tag')], _LiteralTagDecs = [Node, CoveredBy('Tag'), CoveredBy('Expression'), CoveredBy('NodeChild')], _PunctuatorDecs = [Literal, Node, InjectFrom(productions)], _KeywordDecs = [Literal, Node, InjectFrom(productions)], _AnyDecs = InjectFrom(productions), Symbol.for('@bablr/fragment'))]({ props: { rootMatcher } }) { yield* eatMatchTrivia(); yield eat(rootMatcher); yield* eatMatchTrivia(); } *Stream() { while (yield eatMatch(m`.[]: <_Tag />`)); } *Expression() { yield eat(m`<__Any />`, [m`<Document '<!' />`, m`<Node '<' />`]); } *Tag() { yield eat(m`<__Any />`, [m`<NullTag 'null' />`, m`<InitializerTag /\[\]|undefined/ />`, m`<AttributeDefinition '{' />`, m`<ReferenceTag /[.#@a-zA-Z\u0060\u{80}-\u{10ffff}]/ />`, m`<BindingTag ':' />`, m`<LiteralTag /['"]/ />`, m`<DoctypeTag '<!' />`, m`<GapTag '<//>' />`, m`<ShiftTag '^^^' />`, m`<CloseNodeTag '</' />`, m`<OpenNodeTag '<' />`]); } *Document() { yield eatMatch(m`doctype$: <DoctypeTag '<!' />`, o({}), o({ bind: true })); yield* eatMatchTrivia(); yield eat(m`tree$: <Node />`, o({ forceFragment: true })); } *DoctypeTag() { yield eat(m`openToken: <*Punctuator '<!' { balancedSpan: 'Tag', balanced: '>' } />`); yield eat(m`version$: :JSON: <*UnsignedInteger />`); yield eat(m`versionSeparatorToken: <*Punctuator ':' />`); yield eat(m`doctypeToken$: <*Keyword 'cstml' />`); yield* eatMatchTrivia(); yield eat(m`closeToken: <*Punctuator '>' { balancer: true } />`); } *ReferenceTag({ ctx }) { let type; if (type = yield match(re`/[.#@_]/`)) { yield eat(m`type: <*Punctuator ${buildString(ctx.sourceTextFor(type))} />`); } else { yield eat(m`type: null`); } if (!type || ctx.sourceTextFor(type) === '#') { if (type) { yield eatMatch(m`name$: <Identifier />`, o({}), o({ bind: true })); } else { yield eat(m`name$: <Identifier />`); } } else { yield eat(m`name$: null`, o({}), o({ bind: true })); } yield* eatMatchTrivia(); if (yield eatMatch(m`openIndexToken: <*Punctuator '[' { balanced: ']' } />`, o({}), o({ bind: true }))) { yield* eatMatchTrivia(); yield eat(m`closeIndexToken: <*Punctuator ']' { balancer: true } />`); } else { yield eat(m`closeIndexToken: null`); } yield* eatMatchTrivia(); yield eat(m`flags: <ReferenceFlags />`); yield* eatMatchTrivia(); yield eat(m`sigilToken: <*Punctuator ':' />`); } *ReferenceFlags() { yield eatMatch(m`expressionToken: <*Punctuator '+' />`, o({}), o({ bind: true })); yield eatMatch(m`hasGapToken: <*Punctuator '$' />`, o({}), o({ bind: true })); } *BindingTag() { yield eat(m`openToken: <*Punctuator ':' />`); yield eatMatch(m`languagePath: <IdentifierPath />`); yield eat(m`closeToken: <*Punctuator ':' />`); } *GapTag() { yield eat(m`sigilToken: <*Punctuator '<//>' />`); } *ShiftTag() { yield eat(m`sigilToken: <*Punctuator '^^^' />`); } *NullTag() { yield eat(m`sigilToken: <*Keyword 'null' />`); } *InitializerTag() { let arr; if (arr = yield eatMatch(m`sigilToken: <*Punctuator '[]' />`)) {} else if (yield eat(m`sigilToken: <*Keyword 'undefined' />`)) {} yield defineAttribute('isArray', !!arr); } *AttributeDefinition() { yield eatMatch(m`openToken: <*Punctuator '{' { balanced: '}' } />`); yield* eatMatchTrivia(); yield eat(m`key$: <IdentifierPath />`); yield* eatMatchTrivia(); yield eat(m`sigilToken: <*Punctuator ':' />`); yield* eatMatchTrivia(); yield eat(m`value$: :JSON: <_Expression />`); yield* eatMatchTrivia(); yield eat(m`closeToken: <*Punctuator '}' { balancer: true } />`); } *Node({ props }) { let open = yield eat(m`open: <OpenNodeTag />`, o(props)); yield* eatMatchTrivia(); const flags = open.get('flags'); const balanced = open.attributes.balanced; const token = !!flags?.get('tokenToken'); const selfClosing = !balanced; yield eat(m`children[]$: []`); if (selfClosing) { yield eat(m`close: null`); } else { while ((yield match(re`/./s`)) && !(yield match('</'))) { yield eat(m`children[]$: <_NodeChild />`, o({ token })); yield* eatMatchTrivia(); } yield eat(m`close: <CloseNodeTag />`); } } *NodeChild({ props: { token } }) { if (token) { yield eat(m`<__Any />`, [m`<AttributeDefinition '{' />`, m`<Property '@' />`, m`<LiteralTag /['"]/ />`]); } else { yield eat(m`<__Any />`, [m`<AttributeDefinition '{' />`, m`<Property /./s />`]); } } *Property({ ctx }) { let ref = null; if (yield match('^^^')) { yield eat(m`reference$: <ShiftTag />`); } else { ref = yield eatMatch(m`reference$: <ReferenceTag />`, o({}), o({ bind: true })); } yield* eatMatchTrivia(); yield eatMatch(m`binding$: <BindingTag ':' />`, o({}), o({ bind: true })); yield* eatMatchTrivia(); yield eat(m`value$: <_PropertyValue />`, o({ allowFragment: ref && ctx.sourceTextFor(ref.get('type')) === '_' })); } *PropertyValue({ props: { allowFragment } }) { yield eat(m`<__Any />`, [m`<NullTag 'null' />`, m`<GapTag '<//>' />`, m`<InitializerTag /\[\]|undefined/ />`, [m`<Node /\<[^#@]|['"]/ />`, o({ allowFragment, propertyValue: true })]]); } *NodeFlags() { yield eatMatch(m`tokenToken: <*Punctuator '*' />`, o({}), o({ bind: true })); yield eatMatch(m`hasGapToken: <*Punctuator '$' />`, o({}), o({ bind: true })); yield eatMatch(m`fragmentToken: <*Punctuator '_' />`, o({}), o({ bind: true })); yield eatMatch(m`multiFragmentToken: <*Punctuator '_' />`, o({}), o({ bind: true })); } *OpenNodeTag({ s, props: { forceFragment = false, allowFragment = true, propertyValue = false } }) { const outerSpan = s.span; if (yield match(re`/['"]/`)) { yield eat(m`openToken: null`); yield eat(m`flags: null`); yield eat(m`type: null`); yield eat(m`literalValue: :JSON: <String />`); yield eat(m`attributes: null`); yield eat(m`selfClosingTag: null`); yield eat(m`closeToken: null`); return; } yield eat(m`openToken: <*Punctuator '<' { balancedSpan: 'Tag', balanced: '>' } />`); let flags = yield eat(m`flags: <NodeFlags />`); let type = null; let fragmentFlag = !!flags.get('fragmentToken'); let multiFragmentFlag = !!flags.get('multiFragmentToken'); if (forceFragment && !fragmentFlag) { yield fail(); } if (!allowFragment && fragmentFlag) { yield fail(); } if (propertyValue && fragmentFlag && !multiFragmentFlag) { yield fail(); } let isFragment = fragmentFlag; if (isFragment) { yield eat(m`type$: null`); } else { type = yield eat(m`type$: <Identifier />`); } if (!type && !fragmentFlag) { yield fail(); } let sp = type ? yield* eatMatchTrivia() : null; if (type && sp && (yield match(re`/['"]/`))) { yield eat(m`literalValue$: :JSON: <String />`); sp = yield* eatMatchTrivia(); } else { yield eat(m`literalValue$: null`); } if (type) { yield eatMatch(m`attributes$: :JSON: <Object '{' />`, o({}), o({ bind: true })); yield* eatMatchTrivia(); } else { yield eat(m`attributes$: null`); } let sc; if (!isFragment) { sc = yield eatMatch(m`selfClosingToken: <*Punctuator '/' />`, o({}), o({ bind: true })); } else { sc = yield eat(m`selfClosingToken: null`); } const balanced = !sc && (s.depths.path > 0 || outerSpan !== 'Bare'); yield defineAttribute('balanced', balanced); yield defineAttribute('balancedSpan', balanced ? 'NodeChildren' : null); yield eat(m`closeToken: <*Punctuator '>' { balancer: true } />`); } *CloseNodeTag() { yield eat(m`openToken: <*Punctuator '</' { balanced: '>' } />`); yield eat(m`closeToken: <*Punctuator '>' { balancer: true } />`); } *IdentifierPath() { yield eat(m`segments[]$: <Identifier />`); while (yield match('.')) { yield eat(m`#separatorTokens[]: <*Punctuator '.' />`); yield eat(m`segments[]$: <Identifier />`); } } *Identifier() { let q; q = yield eatMatch(m`openToken: <*Punctuator ${buildString('`')} { balanced: ${buildString('`')} } />`, o({}), o({ bind: true })); yield eat(m`content: <*IdentifierContent { span: 'Identifier' } />`, o({ quoted: !!q })); if (q) { yield eat(m`closeToken: <*Punctuator ${buildString('`')} { balancer: true } />`, o({}), o({ bind: true })); } else { yield eat(m`closeToken: null`); } } *IdentifierContent({ props: { quoted = false } }) { let lit, esc; do { if (esc = yield match('\\')) { esc = yield eatMatch(m`@: <EscapeSequence />`); } else { if (!quoted) { lit = yield eatMatch(re`/[a-zA-Z\u{80}-\u{10ffff}][a-zA-Z0-9_\u{80}-\u{10ffff}-]*/`); } else { lit = yield eatMatch(re`/[^\u0060\r\n]+/`); } } } while (lit || esc); } *LiteralTag() { yield eat(m`value: :JSON: <String />`); } *Punctuator() {} *EscapeSequence({ ctx, state: { span } }) { if (!span.startsWith('Identifier')) { yield fail(); } yield eat(m`sigilToken: <*Punctuator '\\' { openSpan: 'Escape' } />`); let codeNode = yield eat(m`code: <EscapeCode { closeSpan: 'Escape' } />`); let cooked; const type = ctx.sourceTextFor(codeNode.get('typeToken')); const value = ctx.sourceTextFor(codeNode.get('value')); if (span !== 'Identifier') { throw new Error('not implemented'); } if (type === 'u') { cooked = String.fromCharCode(parseInt(value, 16)); } else { throw new Error(); } yield defineAttribute('cooked', cooked); } *EscapeCode() { yield eat(m`typeToken: <*Keyword 'u' />`); if (yield eatMatch(m`openToken: <*Punctuator '{' { balanced: '}' } />`, o({}), o({ bind: true }))) { yield eat(m`value$: :JSON: <*UnsignedHexInteger />`); yield eat(m`closeToken: <*Punctuator '}' { balancer: true } />`); } else { yield eat(m`value$: :JSON: <*UnsignedHexInteger /[\da-fA-F]{4}/ />`); yield eat(m`closeToken: null`); } } *Keyword() {} *Any() {} };