Optional terms in InterpretedLanguageGrammar

Jul 8, 2014 at 11:30 PM
I'm deriving from InterpretedLanguageGrammar. It's my understanding that each non-termninal needs its own type, in this case. So, I have a whole bunch of empty types.

Now, for optional terminals (i.e. with the .Q() method), it looks like I also need a type. Is this correct? The code listing below fails when creating the AstNode for the "unsigned?" term.
  public class MyGrammar : InterpretedLanguageGrammar
    public MyGrammar()
      : base(true)
      // 1. Terminals


      // 2. Non-terminals
      var basicType = new NonTerminal("BasicType", typeof(BasicTypeNode));

      // 3. BNF rules
      basicType.Rule = ToTerm("unsigned").Q() + "char" | "short" | "long";
Jul 9, 2014 at 7:29 PM
First, do not use Q() - it was introduced initially but later deprecated, with the biggest reason - situation like yours, it brings a lot of confusion. Yes, you do need AST node for this or any optional term
Jul 9, 2014 at 10:26 PM
OK. Thanks! So should I use the following paradigm instead of Q():
      KeyTerm comma = ToTerm(",", "comma");
      NonTerminal comma_opt = new NonTerminal("comma_opt", Empty | comma);
Regarding required AST nodes, I just made a single empty class for all the terms that I don't want to deal with right now--that works.
Jul 10, 2014 at 6:42 AM
yep, looks right
Aug 9, 2014 at 7:17 AM
I know this thread has already been solved, but I wanted to share an alternative technique. The results are effectively the same, but without leaving all of the extra terms around. Here are some helper functions:
            NonTerminal Optional(string keyword)
                return Optional(ToTerm(keyword, keyword));
            NonTerminal Optional(BnfTerm term)
                NonTerminal nt = new NonTerminal("Optional_" + term.Name, typeof(MyOptionalASTNode));
                    = Empty 
                    | term;
                nt.Flags |= TermFlags.IsTransient | TermFlags.NoAstNode;
                return nt;
The rules can then be clearly written:
basicType.Rule = Optional("unsigned") + "char" | "short" | "long";