handling error states

With the following grammar, a Set should be parsed when we find #{ ...expressions... } .

@top[name=Program] { expression* }

expression { Symbol | Set | Map }
Map { "{" expression* "}" }

@skip {} {
  Set { "#" Map }

@tokens {
  whitespace { (std.whitespace | ",")+ }
  Symbol { std.asciiLetter+ }

When passed the source # (and strict mode off), the # is parsed as a Program(Set) (some kind of partial parse, from error recovery).

Is it possible to detect that this Set is actually not a Set as defined, without inspecting its children? I’m implementing some editing commands and in states like this I would want to treat the # as something else, like Symbol or a specific InvalidTerminalToken. (For my commands to work a Set at least needs to contain its brackets.)

Are you sure there’s no error node in the Set node? Because error recovery should always leave error markers.

Are you sure there’s no error node in the Set node?

It may be there, and I’m just not sure how/where to look. I do see that the firstChild of the Set has the name and its type.props is {"0": true, propData: [{name: "error", from: null}, ""]}. The Set itself has empty type.props.

I’m guessing there is some way of reading NodeProps that I am missing - from the docs I was expecting to find an error key somewhere: https://lezer.codemirror.net/docs/ref/#tree.NodeProp^error (I admittedly have not fully grokked how NodeProps work).

I think the prop method is that way. Don’t look at the props object directly—it’s not documented, which means it’s private.

OK. So in this case we find the error not on the Set but on its missing child - <Set>.firstChild.type.prop(NodeProp.error).

The props are static, per node type, so you’ll never have a Set with the error prop set. Rather, there’s an error type that is inserted whenever error recovery is done.

I see, makes sense. So we do a bit of checking to see if a Set node contains an error type.