Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » How to avoid ambiguity
How to avoid ambiguity [message #1850696] Mon, 14 March 2022 18:11 Go to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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:
@MyAnn MyItem {}


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
@Name {}
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,
@ Name {}
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 #1850697 is a reply to message #1850696] Mon, 14 March 2022 19:06 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
did you try to use predicate?

fragment AnnotationName * hidden () :
'@' ->name=ID?
;


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to avoid ambiguity [message #1850698 is a reply to message #1850697] Mon, 14 March 2022 19:44 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
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 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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]

Report message to a moderator

Re: How to avoid ambiguity [message #1850700 is a reply to message #1850698] Mon, 14 March 2022 19:57 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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]

Report message to a moderator

Re: How to avoid ambiguity [message #1850702 is a reply to message #1850700] Mon, 14 March 2022 20:11 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
can you please provide complete grammar?

Item:
   {Item}(annotations+=Annotation)?
   name=ID? 
   '{' 
   '}'
;

Annotation:
  {Annotation}
  AnnotationName ( '(' ')' )?
;

fragment AnnotationName * hidden () :
   '@' ->name=ID?
;


does not complain


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Mon, 14 March 2022 20:15]

Report message to a moderator

Re: How to avoid ambiguity [message #1850703 is a reply to message #1850702] Mon, 14 March 2022 20:23 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Thanks, I will. My grammar is in reality a bit more complex. I will start at the grammar you provided and try to get to my actual grammar.
Re: How to avoid ambiguity [message #1850704 is a reply to message #1850703] Mon, 14 March 2022 20:45 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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]

Report message to a moderator

Re: How to avoid ambiguity [message #1850705 is a reply to message #1850704] Mon, 14 March 2022 20:50 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
fragment AnnotationName * hidden () :
->'@' ->name=ID?
;

am not sure if this gives you the correct result for the ambigous model


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to avoid ambiguity [message #1850706 is a reply to message #1850705] Mon, 14 March 2022 21:05 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
Great, thank you. That works for this example. I will now try to incorporate this solution pattern into my real grammar - thanks for your great input!
Re: How to avoid ambiguity [message #1850740 is a reply to message #1850706] Tue, 15 March 2022 18:16 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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 #1850741 is a reply to message #1850740] Tue, 15 March 2022 19:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
i really suggest to generate a debug grammar and get familiar with antlrworks

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to avoid ambiguity [message #1850742 is a reply to message #1850741] Tue, 15 March 2022 19:40 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
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?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Tue, 15 March 2022 19:43]

Report message to a moderator

Re: How to avoid ambiguity [message #1850743 is a reply to message #1850742] Tue, 15 March 2022 19:44 Go to previous messageGo to next message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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 #1850744 is a reply to message #1850743] Tue, 15 March 2022 19:48 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
no you can configure
workflow
to have a debug grammar
you can load into antlrworks
maybe this helps you to understand where antlr seen the ambiguity


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to avoid ambiguity [message #1850745 is a reply to message #1850744] Tue, 15 March 2022 19:51 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
very naive question:
why fragment and hidden stuff and not a terminal? (+ value converter)

terminal ANNOTATION_NAME :
'@' ID?
;


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Tue, 15 March 2022 19:51]

Report message to a moderator

Re: How to avoid ambiguity [message #1850759 is a reply to message #1850745] Wed, 16 March 2022 08:58 Go to previous message
Konrad Jünemann is currently offline Konrad JünemannFriend
Messages: 93
Registered: December 2018
Member
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.
Previous Topic:Language server not responding to client request
Next Topic:Syntax-Error for LessThan-Keyword
Goto Forum:
  


Current Time: Fri Mar 29 10:16:38 GMT 2024

Powered by FUDForum. Page generated in 0.05347 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top