I’m looking at creating a mixed language parser, and am seeing parsedMixed.
LIke with many references in Lexer and CodeMirror docs, it all just goes to this API docs, which… is great for people that know what they’re doing – but… how does someone how hasn’t clue get started? I’ve read this blurb on parsedMixed
Lezer Reference Manual and… as someone new to lexer, I must ask, “so… how do I use it?”
How do I use parseMixed
?
marijn
July 11, 2022, 6:51pm
2
I have a super simple meta-grammar to try to overlay two languages:
@top Document { entity* }
entity {
GlimmerTemplateTag
}
GlimmerTemplateTag {
"<template>" templateTagContent* "</template>"
}
@external tokens templateTagContent from "./tokens.js" { templateTagContent }
@tokens {
"<template>"[closedBy="</template>"]
"</template>"[openedBy="<template"]
}
This is the language definition I’m using:
export function gjs() {
return new LanguageSupport(gjsLanguage, [javascript().support]);
}
export const gjsLanguage = LRLanguage.define({
parser: metaParser.configure({
wrap: parseMixed((node) => {
console.log(node.name, node);
switch (node.name) {
case 'GlimmerTemplateTag':
return { parser: glimmerParser };
default:
return { parser: javascriptLanguage.parser };
}
}),
}),
});
sample document
const Foo = <template>
{{@arg}}
</template>;
const code = (text) => JSON.stringify(text, null, 4);
<template>
<Foo @arg={{code document.body.innerHTML}} />
</template>
tree
Document [1:0..11:0]
├─ ⚠ [1:0..2:14]: "\n const Foo = "
├─ GlimmerTemplateTag [2:14..4:13]
│ ├─ <template> [2:14..2:24]: "<template>"
│ ├─ ⚠ [2:24..4:2]: "\n {{@arg}}\n "
│ └─ </template> [4:2..4:13]: "</template>"
├─ ⚠ [4:13..8:2]: ";\n\n const code = (text) => JSON.stringify(text, null, 4);\n\n "
├─ GlimmerTemplateTag [8:2..10:13]
│ ├─ <template> [8:2..8:12]: "<template>"
│ ├─ ⚠ [8:12..10:2]: "\n <Foo @arg={{code document.body.innerHTML}} />\n "
│ └─ </template> [10:2..10:13]: "</template>"
└─ ⚠ [10:13..11:0]: "\n"
the console. log is getting hit, but it’s only hitting one node, Document
The examples seemed to imply that all nodes would be hit?
How do I arbitrarily highlight one part of a document with one parser and the rest with the js/an-existing-parser?
I think I figured it out:
Need to return null
for any node that I’m not ready for parsing yet:
export const gjsLanguage = LRLanguage.define({
parser: metaParser.configure({
wrap: parseMixed((node) => {
if (node.type.name === 'Document') return null;
if (node.type.name === 'GlimmerTemplateTag')
return { parser: glimmerParser };
return { parser: javascriptLanguage.parser };
}),
}),
});