2

I would like to parse the following recusive rule which parses simple template classe identifier like foo<bar> foo<bar,baz> foo<bar<baz>> here is the simple grammar:

identifier := A-Z | a-z | _
class_identifier = identifier ?("<" identifier|class_identifier 
                                    ( "," identifier|class_identifier)* 
                                ">") 

I tried to write a parser with x3 like this:

 auto const identifier = x3::rule<class identifier_id, std::string>{"identifier"}
                          = +x3::char_("A-Za-z");

 x3::rule<class class_identifier, std::string> class_identifier = "class_identifier";

 auto const class_identifier_def  = identifier //classname
                                            >> -(x3::string("<")
                                                 >> (identifier | class_identifier)                                           
                                                 >> *(x3::string(",")                                                     
                                                      >> (identifier | class_identifier))
                                                 >> x3::string(">"));
 BOOST_SPIRIT_DEFINE(class_identifier)

But this try fails to parse stuff like this foo<bar<baz>> but foo is fine. Is there some logical error in my grammar or am I using boost spirit wrong since this is a recursive rule?

Exagon
  • 4,798
  • 6
  • 25
  • 53
  • 1
    To make your life easier, I believe `(identifier | class_identifier) >> *(x3::string(",") >> (identifier | class_identifier))` can be replaced with `(identifier | class_identifier) % x3::string(",")`. I wouldn't be surprised if that could be simplified to `% ','`, too, along with other places where a literal wouldn't interfere with operator overloading. – chris May 26 '16 at 16:43
  • 1
    Indeed. `% ','` is fine – sehe May 26 '16 at 16:45
  • even if i parse into a string and want the `','` to be in the string? – Exagon May 26 '16 at 16:52
  • 2
    @Exagon not then, indeed. There's an implicit `x3::omit[]` around the delimiter parser in the list operator. – sehe May 26 '16 at 21:08

1 Answers1

3

I have found why this fails to parse. I hade to change this (identifier | class_identifier) to this (class_identifier | identifier) because it also the class_identifier rule also starts with an identifier. thats why it tried to parse everytime with the identifier rule and then fails at the <

Exagon
  • 4,798
  • 6
  • 25
  • 53
  • 1
    I think that currently the second branch of the alternative parser is never taken. I haven't tested it so I may be wrong but I'm pretty sure that you don't even need the alternative operator as long as you have the optional in `class_identifier`. If in the future you change the attributes (from a plain string to some kind of AST) your current definition would be better (removing that optional). – llonesmiz May 27 '16 at 06:15