Hi everyone!
I am working a very simple language implementation (mostly expressions) and integrating it to monaco editor.
There are a huge amount of examples about defining a language or on evaluating it.
However, after a week of info digging, I am still stuck how to (1) give more meaningful error messages and (2) detect context at caret position.
Let's see what I am looking for:
Error messages:My main problem is that the parser returns meaningless (for users) "No viable alternative..." for partial expressions. Also, there is no normal entries in AST for these expressions.
Let's see an example:
My language contains an if expression (like in Kotlin):
ifExpression
: IF NL* condition NL* trueStatement (NL* ELSE NL* falseStatement )?
This is correct, but when -- for example the trueStatement is missing: `if (x < 2) else 42` it gives the no viable error which is not too user frindly. My idea was to use validator evaluator (visitor pattern, as it already is used to detect semantic problems) and handle partial if statement by checking the children. However, as it doesn't match the rule, there is no visitor call. Also I find that I could define rule for partial expression:
ifExpression
: IF NL* condition NL* trueStatement (NL* ELSE NL* falseStatement )? # completeIfExpression
| IF NL* condition? NL* trueStatement? ELSE? falseStatement? # errPartialIfExpression
;
Then I could handle this case nicely, but it would polute both my grammar and my visitor (the runtime, real evaluator visitor should throw error if this rule applied). So this works, but not nice. Also, it only handles the problem of if, so I may have to polute the grammar greatly to support other position.
Context detection for context sensitive autocompleteThe same problem appears when I would like to add intelligent suggestions. For this, what I need is to parse the script only until the caret and check what the next token could be and (for example) if it is a identifier, then list the available ones. The listing part is ok, but my problem the same: partial expressions doesn't parsed into the AST.
For example, when I open the condition parenthesis ( `if (` ), I would like to detect that the next token could be an identifier, and offer the options. However, as an unclosed paren is not viable condition, so it is not parsed as a partial condition. There are several other (operators, function arguments, assignment, etc.) where identifiers used, but the expression is partial before specifying one.
So, what I am looking for is some help pointing me toward examples and detailed info about how to do it correctly. I tried to do it with special evaluator, error listener, etc, but failed to find a solution.
Any idea or hint is welcome, examples are even more welcome! Thank you!
(BTW: I use this in a typescript environment based on the antlr-ng as builder and antlr4ng as frontend lib.)
Balage