How to avoid ambiguity [message #1850696] |
Mon, 14 March 2022 18:11  |
Eclipse User |
|
|
|
Hi,
I have a grammar that should be able to model Annotations.
The simplified grammar looks like this:
Item:
(annotations+=Annotation)?
name=ID
'{'
'}'
;
Annotation:
{Annotation}
AnnotationName ( '(' ')' )?
;
fragment AnnotationName * hidden () :
'@' name=ID
;
It should work as follows:
The problem is that I would like to allow annotations with an empty name (just syntactically, as I later want to propose all available annotation names when the user just enters an '@' character). However, just making the name optional by modifying it to
fragment AnnotationName * hidden () :
'@' (name=ID)?
;
does not work, as now the expression would introduce ambiguity (is "Name" the name of the annotation or the item?).
I tried to "force" whitespaces after the Annotation name, but this did not work either - I still get "no viable alternative at input" error, although the dsl does parse successfully.
fragment AnnotationName * hidden () :
'@' (name=ID | WS)
;
After all, should parse as a single Item with name "Name" that possesses an unnamed annotation.
Any ideas how I would design a grammar like this?
|
|
|
|
Re: How to avoid ambiguity [message #1850698 is a reply to message #1850697] |
Mon, 14 March 2022 19:44   |
Eclipse User |
|
|
|
Hi
I always try to avoid syntactic predicates, since IMHO the need for such a fix is a sign that the grammar is poorly designed and consequently hides surprises for your users.
Perhaps it's time to take a step back. Are blank named annotations really such a good idea? If they really are then you perhaps need a syntax for the blank name. If you allow an annotation name to be an ID or STRING then you could use @'' for the blank name. Or braces or ...
Regards
Ed Willink
|
|
|
Re: How to avoid ambiguity [message #1850699 is a reply to message #1850697] |
Mon, 14 March 2022 19:50   |
Eclipse User |
|
|
|
Quote:
did you try to use predicate?
fragment AnnotationName * hidden () :
'@' ->name=ID?
;
I did, but it apparently did nothing - at least nothing I noticed. I still get the "the decision cannot distinguish between alternative(s)"... error when parsing the grammar. Is there any way I can debug in more detail what goes wrong?
( I tried both the -> and the => predicates, both at the AnnotationName and Item locations)
[Updated on: Mon, 14 March 2022 19:57] by Moderator Report message to a moderator
|
|
|
Re: How to avoid ambiguity [message #1850700 is a reply to message #1850698] |
Mon, 14 March 2022 19:57   |
Eclipse User |
|
|
|
Ed Willink wrote on Mon, 14 March 2022 19:44
Are blank named annotations really such a good idea?
I don't actually want to allow blank named annotations - I just want to support them syntactically, not semantically. I wrote a validation that throws errors for blank annotations. The reason I want to allow blank annotations is that I want to propose (during content assist) which annotations are allowed at this specific item - in order to do so I need the (following) item to be parseable.
To be more specific: when the user types a '@' character content assist should already propose all valid annotations. But if the model is not syntactically correct in this state, I cannot do that (as I cannot analyze the following item).
Edit: the rule my grammar should follow is actually quite simple, I just don't know how to implement it, if it is possible at all:
- if there follows an ID directly after the '@' character (without any whitespaces), then this is the name of the annotation, no matter what characters follow.
- if there follows no ID, then the name of the annotation should be blank.
[Updated on: Mon, 14 March 2022 20:08] by Moderator Report message to a moderator
|
|
|
|
|
Re: How to avoid ambiguity [message #1850704 is a reply to message #1850703] |
Mon, 14 March 2022 20:45   |
Eclipse User |
|
|
|
OK, the problem seems to be that the item's block brackets are optional too.
This should work (even without predicate):
Item:
{Item}(annotations+=Annotation)?
name=ID
'{'
'}'
;
Annotation:
{Annotation}
AnnotationName ( '(' ')' )?
;
fragment AnnotationName * hidden () :
'@' name=ID?
;
This should not work (with or without predicate):
Item:
{Item}(annotations+=Annotation)?
name=ID
(
'{'
'}'
)?
;
Annotation:
{Annotation}
AnnotationName ( '(' ')' )?
;
fragment AnnotationName * hidden () :
'@' ->name=ID?
;
Is there another trick I could try?
[Updated on: Mon, 14 March 2022 20:45] by Moderator Report message to a moderator
|
|
|
|
|
Re: How to avoid ambiguity [message #1850740 is a reply to message #1850706] |
Tue, 15 March 2022 18:16   |
Eclipse User |
|
|
|
I tried to extrapolate the proposed solution to my real grammar and was unable to get it to work. Here is a fairly minimal grammar that illustrates the problem:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
enumerations+=Enumeration*;
Enumeration:
{Enumeration}
(annotations+=Annotation)?
name=ID
'{'
(
encodings+=Encoding ( ',' encodings+=Encoding)*
)?
'}'
;
Encoding:
Annotations
name=ID
;
fragment Annotations * :
(annotations+=Annotation)*
;
Annotation:
{Annotation}
AnnotationName ( '(' ')' )?
;
fragment AnnotationName * hidden () :
(
'@' name=ID?
)
;
Here is a couple of test cases that should all parse correctly:
MyEnumeration {
Test1,
@ABC()
Test2,
@ABC
Test3,
@ABC()
@DEF
Test4,
@
Test5,
@()
Test6,
@DEF
@
@()
@ABC()
Test7,
}
The grammar posted above throws the error:
error(202): ../org.xtext.example.mydsl/src-gen/org/xtext/example/mydsl/parser/antlr/internal/InternalMyDsl.g:356:3: the decision cannot distinguish between alternative(s) 1,2 for input such as "RULE_ID EOF EOF"
I tried to debug it with ANTLRWorks, with no success - I am probably dooing it wrong, but ANTLRworks shows no problems to me. I then tried to use predicates, following the guide here: https://www.slideshare.net/schwurbel/getting-rid-of-backtracking (written by Jan Köhnlein), but to no avail.
Maybe you guys have another hint what I could try? Or is it simply not possible to create a grammar like this (with justifiable effort)?
|
|
|
|
Re: How to avoid ambiguity [message #1850742 is a reply to message #1850741] |
Tue, 15 March 2022 19:40   |
Eclipse User |
|
|
|
and maybe start analyzing the real minimal model
Model2:
encodings+=Encoding
;
Encoding:
(annotations+=Annotation)*
name=ID
;
Annotation:
{Annotation}
AnnotationName ( '(' ')' )?
;
fragment AnnotationName * hidden () :
(
'@' name=ID?
)
;
btw is this an existing lang?
[Updated on: Tue, 15 March 2022 19:43] by Moderator Report message to a moderator
|
|
|
Re: How to avoid ambiguity [message #1850743 is a reply to message #1850742] |
Tue, 15 March 2022 19:44   |
Eclipse User |
|
|
|
Thanks,
the grammar I provided is the debug grammar...
But OK, I think I will look into ANLRWorks a bit more. I guess the simplest solution is to just introduce a couple of new keywords into my grammar. This should simplify things a lot.
Thanks for your help!
|
|
|
|
|
Re: How to avoid ambiguity [message #1850759 is a reply to message #1850745] |
Wed, 16 March 2022 08:58  |
Eclipse User |
|
|
|
Quote:
no you can configure
workflow
to have a debug grammar
Oh, I misunderstood you. Yeah, I already did that - for some reason the debug-grammer did not show a disambiguity while the "real" grammer did.
Quote:
why fragment and hidden stuff and not a terminal? (+ value converter)
Thank you so much, that was exactly the right idea. Don't know why I did not think of it, but this solves the problem perfectly. It also simplifies the grammar and I don't have to deal with predicates. Works fine no, even in my real grammar. Thanks!
Regarding my other approach: I don't think it is possible to achieve what I want using the "fragment + hidden()" approach. At least I did not get it to work, even with the simplest grammar. But I will not look into it any longer as the Terminal-approach is much cleaner.
|
|
|
Powered by
FUDForum. Page generated in 0.05014 seconds