@bablr/language_enhancer-en-jsx
Version:
A BABLR grammar to enhance a JS-family language with JSX
182 lines • 6.97 kB
JavaScript
/* @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;