How do you actually use parseMixed?

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? :smiley:

Maybe with the mixed language parsing example.

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 };
    }),
  }),
});

Progress: