Is it possible to enforcing type of function params with boost::spirit QI

54 Views Asked by At

I'm writing the parser to parse a list of built in functions. For example:

Function1(int p1, string p2)

Function2(string p1, int p2, string p3)

Function3(string p1, string p2, int p3, int p4, string p5) etc.

I don't have any issue writing rule to parse these functions individually like create AST struct for each then write rule to parse them like the below for Function1 rule:

func1_ = lit("Function1") >> '(' >> int_ >> ',' >> literal_ >> ')';

But this function list is quite long so I will hit the limitation of allow variant. I'm thinking of just create a single AST struct to parse all of them like this:

struct FunctionTemplate {
  std::string name;
  std::vector<boost::variant<int, std::string>> params
};

For simplicity, I'm just using int and string as param's types.

And for the rule, I could do:

params_ = int_ | literal_;
func_tpl_ = 
  (raw["Function1"] >> '(' >> (params_ % ',') >> ')')
  | (raw["Function2"] >> '(' >> (params_ % ',') >> ')')
  ; 

It parsed just fine but this rule will also allow wrong param's datatype order as for Function1, it will also accept string then int instead of the other way around. This will also accept more params then it should.

So is it possible to enforce the param's datatype order and number of params so that it not only parse correctly but also match the right order and right number of the params?

Thanks

1

There are 1 best solutions below

2
sehe On

But this function list is quite long so I will hit the limitation of allow variant. I'm thinking of just create a single AST struct to parse all of them like this

You can write your grammar productions like you intend, just make it so that the arguments get parsed into a common datatype (e.g. numbers instead of int_ directly, with number as a rule<It, MyArgType>. That way you can parse into a generic (non-variant) datatype while still following different productions for different names.

In fact, for extensibility/maintainability you might use the Nabialek Trick here and store individual functions in separate rules of the same declared attributes. I must have a number of examples on this site that will probably show you some scriptlike grammars with a very similar approach.