Example of PerNode NodeProp

Can someone provide an example of how to use a perNode NodeProp with an existing Lezer grammar / parser?

I tried the following

import { parser as baseParser } from './spreadsheet.grammar';
export const cellReferenceProp = new NodeProp({ perNode: true });

const parser = baseParser.configure({
  props: [
    cellReferenceProp.add((type: NodeType) => {
      console.log("type", type);

But ran into

Uncaught RangeError: Can't add per-node props to node types

I’m trying to extend this spreadsheet language to parse and keep cell references as props in the CellToken.

For example,

=A1

turns into

Program
 └─ Reference
     └─ ReferenceItem
         └─ CellToken

and when I access that node in a StatePlugin, I would want

if (node.name === 'CellToken') {
  const cellRef = node.tree.prop(cellReferenceProp) // { row: 0, col: 0 } 
}

You can’t configure a parser’s set of node types to add per-node props, obviously, since the parser has a node types, not a set of individual nodes. How are you planning to add these? There’s no way to add custom per-node props in a Lezer-generated LR parser. They do use those for a few things (like context hashes and lookahead distances) internally, but to do something like resolve references at parse time and store them in the tree, you’d have to create a custom parser.

1 Like

Ah got it. I’m trying to reimplement the parser that hyperformula uses (internally it built on chevrotain), and was looking something similar in code to

where for some cell tokens, you’re able to define a javascript function to add metadata to individual AST nodes based on the AST type.

The metadata is useful because for some interactions, like turning A2 into A$2, it’s easier to operate on

{ row: 2, col: 0, absoluteCol: false, absoluteRow: false} // A2
{ row: 2, col: 0, absoluteCol: true, absoluteRow: false} // A$2

Hyperformula doesn’t come with a formula editor, so all the parsing etc has to be built from scratch.