I’m trying to write a Lezer Grammar for Glimmer.
The tree-sitter equiv is here: tree-sitter-glimmer/grammar.js at main · alexlafroscia/tree-sitter-glimmer · GitHub
But it also completely parses HTML as well, which I’m hoping to avoid by using parseMixed
– so I only want to parse things between {{
and }}
and ignore everything else (for now (I do need to parse some HTML stuff for better component invocation highlighting, named-blocks, etc))
I’m running in to an issue right now where where I have two types errors (when running my tests):
SyntaxError: No parse at 5 # or whatever number
or
Error: Unexpected end of Value
(specifically when trying to test strings (which could be either double or single quoted).
So, I guess my questions are:
- where do I go from here?
- how do I debug?
- I really hope I don’t need any “tokens.js” file like a bunch of the example grammars have (I don’t want to write JS
) – I don’t have to, do I?
Here is my grammar so far:
@top Glimmer {
list<
Expression
| Block
| BlockComment
>
}
Expression { moustache<SubExpression> }
Block { StartBlock any* EndBlock }
StartBlock { moustache<"#" name SubExpression? As?> }
As { kw<"as"> "|" list<name> "|" }
EndBlock { moustache<"/" name> }
SubExpression { list<Value> NamedArgs? }
Value {
boolean
| null
| undefined
| string
| Number
| Invocation
| Argument
| ThisExpression
| PropertyPath
}
Invocation { "(" SubExpression ")" }
NamedArgs { list<Pair> }
Pair { string "=" Value }
Argument { "@" name }
ThisExpression { this "." PropertyPath }
PropertyPath { name ("." name) }
boolean {
@specialize[@name=BooleanLiteral]<identifier, "true" | "false">
}
null {
@specialize[@name=Literal]<identifier, "null">
}
undefined {
@specialize[@name=Literal]<identifier, "undefined">
}
LongComment { "!--" any* "--" }
ShortComment { "!" any* }
BlockComment { moustache<(LongComment | ShortComment)> }
@tokens {
Number { int frac? }
int { '0' | $[1-9] @digit* }
frac { '.' @digit+ }
this { "this" }
identifierChar { @asciiLetter | $[_$\u{a1}-\u{10ffff}] }
word { identifierChar (identifierChar | @digit)* }
identifier { word }
@precedence { identifier, this }
@precedence { name, identifier, this }
name { word }
any { $[.] }
attributeContentDouble { !["]+ }
attributeContentSingle { ![']+ }
string {
"\"" attributeContentDouble* "\"" |
"\'" attributeContentSingle* "\'"
}
space { (" " | "\t" | "\r" | "\n")+ }
@precedence { " ", space }
}
@skip { space }
// Helper And Special Things
list<item> { item (" " item)* }
kw<term> { @specialize[@name={term}]<identifier, term> }
moustache<content> { "{{" content "}}" }
@external propSource glimmerHighlighting from './highlight'
And some failing tests:
# Multiple Integer
{{42}} and {{24}}
==>
Glimmer(
Expression(
SubExpression(
Value(Number)
)
)
Expression(
SubExpression(
Value(Number)
)
)
)
# Basic - Double
{{"Some String"}}
==>
Glimmer(
Expression(
SubExpression(
Value(String)
)
)
)
And here is my code so far: Implementation by NullVoxPopuli · Pull Request #2 · NullVoxPopuli/glimdown · GitHub
Thanks!