UNPKG

@bablr/language_enhancer-en-jsx

Version:

A BABLR grammar to enhance a JS-family language with JSX

182 lines 6.97 kB
/* @macrome * @generatedby @bablr/macrome-generator-bablr * @generatedfrom ./grammar.macro.js#d37b510eb200a6a3a935651b41be6665f0d72f54 * 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"; import { CoveredBy, InjectFrom, Node, UndefinedAttributes } from '@bablr/helpers/decorators'; import { spam as m } from '@bablr/helpers/shorthand'; import * as productions from '@bablr/helpers/productions'; import { o, eat, eatMatch, defineAttribute, shiftMatch, fail } from '@bablr/helpers/grammar'; import { triviaEnhancer } from '@bablr/helpers/trivia'; export const enhanceLanguageWithJSX = language => { let _initProto, _NodeDecs, _InterpolationDecs, _OpenTagDecs, _TextDecs, _IdentifierDecs, _MemberExpressionDecs, _PunctuatorDecs, _LiteralDecs; if (language.dependencies.JSX) throw new Error(); let jsxLanguage = Object.freeze({ canonicalURL: 'https://bablr.org/languages/universe/jsx', dependencies: Object.freeze({ JS: language.canonicalURL }), grammar: triviaEnhancer({ triviaIsAllowed: s => ['Tag', 'Interpolation'].includes(s.span), triviaMatcher: m`#: :JS.Comment: <_Trivia /[ \n\r\t]|\/\/|\/\*/ />` }, class JSXGrammar { static { [_initProto] = _applyDecs(this, [[_NodeDecs, 2, "Node"], [_InterpolationDecs, 2, "Interpolation"], [_OpenTagDecs, 2, "OpenTag"], [Node, 2, "CloseTag"], [_TextDecs, 2, "Text"], [Node, 2, "Attribute"], [_IdentifierDecs, 2, "Identifier"], [_MemberExpressionDecs, 2, "MemberExpression"], [_PunctuatorDecs, 2, "Punctuator"], [_LiteralDecs, 2, "Literal"]], []).e; } constructor() { _initProto(this); } *[(_NodeDecs = [CoveredBy('NodeChild'), Node], _InterpolationDecs = [CoveredBy('NodeChild'), Node], _OpenTagDecs = [UndefinedAttributes(['balanced', 'balancedSpan']), Node], _TextDecs = [CoveredBy('NodeChild'), Node], _IdentifierDecs = [CoveredBy('NodeType'), Node], _MemberExpressionDecs = [CoveredBy('NodeType'), Node], _PunctuatorDecs = [InjectFrom(productions), Node], _LiteralDecs = [InjectFrom(productions), Node], "Node")]({ ctx }) { let open = yield eat(m`open: <OpenTag />`); let openType = open.get('type'); if (open.get('selfClosingTagToken')) { yield eat(m`close: null`); return; } yield eat(m`children[]$: <_Children />`, o({}), o({ allowEmpty: true })); let close = yield eat(m`close: <CloseTag />`); let closeType = close.get('type'); while (openType.type === closeType.type) { if (openType.type === 'MemberExpression') { if (ctx.sourceTextFor(openType.get('property')) !== ctx.sourceTextFor(closeType.get('property'))) { break; } openType = openType.get('object'); closeType = closeType.get('object'); } else { if (closeType.type === openType.type && ctx.sourceTextFor(openType.get('value')) === ctx.sourceTextFor(closeType.get('value'))) { return; } else { break; } } } yield fail(); } *Children() { while (yield eatMatch(m`<__NodeChild />`)) {} } *NodeChild() { (yield eatMatch(m`<Interpolation '{' />`)) || (yield eatMatch(m`<Node '<' />`)) || (yield eat(m`<Text />`)); } *Interpolation() { yield eat(m`openToken: <*Punctuator '{' { balanced: '}', balancedSpan: 'Interpolation' } />`); yield eatMatch(m`value+$: :JS: <__Expression />`, o({}), o({ bind: true })); yield eat(m`closeToken: <*Punctuator '}' { balancer: true } />`); } *OpenTag({ s, props: { fragment } }) { const outerSpan = s.span; yield eat(m`openToken: <*Punctuator '<' { balancedSpan: 'Tag', balanced: '>' } />`); let type; type = !fragment && (yield eatMatch(m`type+$: <__NodeType />`)); if (type) { while (yield eatMatch(m`attributes[]$: <Attribute />`)) {} } else { yield eat(m`attributes$: null`); } let sc; if (type) { sc = yield eatMatch(m`selfClosingTagToken: <*Punctuator '/' />`, o({}), o({ bind: true })); } else { sc = yield eat(m`selfClosingTagToken: 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 } />`); } *NodeType({ s }) { let res; if (!s.holding) { res = yield eat(m`<Identifier />`); } else { res = yield eatMatch(m`<MemberExpression /\g\./ />`); } if (res) { return shiftMatch(m`<__NodeType />`); } } *CloseTag() { yield eat(m`openToken: <*Punctuator '</' { balanced: '>', balancedSpan: 'Tag' } />`); yield eatMatch(m`type+$: <__NodeType />`); yield eat(m`closeToken: <*Punctuator '>' { balancer: true } />`); } *Text() { yield eat(m`value: <*Literal /[^{<>}\g]+/ />`); } *Attribute() { yield eat(m`name$: <Identifier />`, o({ scoped: false })); yield eat(m`sigilToken: <*Punctuator '=' />`); yield eat(m`value$: <__AttributeValue />`); } *AttributeValue() { if (yield eatMatch(m`:JS: <String /['"]/ />`)) {} else if (yield eatMatch(m`<Interpolation '{' />`)) {} } *Identifier({ props: { scoped = true } }) { yield eat(m`:JS: <_Identifier />`, o({ scoped })); } *MemberExpression() { yield eat(m`:JS: <_MemberExpression /\g\./ />`); } *Punctuator() {} *Literal() {} }) }); return Object.freeze({ ...language, dependencies: Object.freeze({ ...language.dependencies, JSX: jsxLanguage }), grammar: triviaEnhancer({ triviaIsAllowed: s => s.span === 'Bare', triviaMatcher: m`#: :Comment: <_Trivia /[ \n\r\t]|\/\/|\/\*/ />` }, class extends language.atrivialGrammar { *Expression(args) { let { s, props: { power } } = args; if (!s.held) { if (yield eatMatch(m`:JSX: <Node />`)) { return shiftMatch(m`<__Expression />`, o({ power })); } else { return yield* super.Expression(args); } } else { return yield* super.Expression(args); } } }) }); }; export default enhanceLanguageWithJSX;