This project has moved and is read-only. For the latest updates, please go here.

Best way to validate list of non-terminals

Jan 7, 2015 at 3:43 AM
Edited Jan 7, 2015 at 3:57 AM

I have been working on a grammar using Irony for a couple of weeks and have made substantial progress. The language is VBA (quite similar to VB6) and the source can be found here.

What I want to do is validate a list of non-terminals, the first check being that there is only one of each 'attribute' within the list (i.e. no duplicate declarations). The relevant source is:
Root = module;
module.Rule = moduleHeader + Optional(NewLinePlus + moduleBody);
moduleHeader.Rule = MakePlusRule(moduleHeader, NewLine, attribute);
moduleHeader.Reduced += ModuleHeaderReduced;

attribute.Rule = ToTerm("Attribute") + attributeType + "=" + attributeValue;
attributeType.Rule = ToTerm("VB_Name") | "VB_GlobalNameSpace" | "VB_Creatable" | "VB_PredeclaredId" | "VB_Exposed" |  "VB_Customizable";
attributeValue.Rule = stringLiteral | "True" | "False";
So you will see that I'm trying to use the moduleHeader.Reduced event to perform this validation however I see that I get multiple fires of this event (which the Irony source says happens for lists). Is this the best approach, or should I be using the AstNodeCreated event or something else entirely?

PS the plus symbols are escaping weirdly, if you know how I can edit this so that it is more readable, let me know.
Jan 27, 2015 at 7:24 AM
sorry for late response
yes, that's true, probably list' Reduced even is fired multiple times, each time new element is added to the list. One thing to do is hook to higher level non-terminal (module), and then run through the list. But on a general note. This kind of rule is in fact 'semantics', not syntax; in c# attribute (some) allow duplicates, in VBA - no. So this semantic rule, so it should be checked/enforced after completing parsing, by analyzing the completed parse tree - or even the AST tree.
Jan 27, 2015 at 8:57 AM
Edited Jan 27, 2015 at 8:57 AM
Thanks for the reply Roman,

I have since been working my way through the Irony source so I have a much better understanding since asking this question. Its because lists are expressed recursively, like:
   list.Rule = item |
               list + item;
ignoring delimiters etc. Since the rule refers back to itself it needs to keep reducing the list each time it finds a new item (this is really for anyone finding this thread as I'm telling you how to suck eggs).

I'm thinking through general ways to deal with this problem. A method which automatically adds the extra layer so that the Reduced event only fires once when the list is complete? Perhaps the method accepts parameters detailing the min/max number of items in the list?

Anyway, you are right with the comment that it is more semantics rather than syntax. I see a lot of questions in these forums with that comment. I guess the problem is that we are creating a derived class from Grammar and it isn't always clear where the separation is between the different layers. I guess it also depends on how Irony is to be used as well. I'm hoping to use it as a language service inside Visual Studio. So I would like to report back semantic issues as well as syntactic, is it possible to push errors back at the AST tree stage?
Jan 27, 2015 at 7:22 PM
I'm pretty sure you can (push errors) - just add error to parsing context while you're running post-parse activities