I have written a verilog parser with bison, and use boost::variant to store all the difference cases for each variant of each rules. I use a small example, the BNF rule of expression, to show my data structure:
expression :
primary
| expression + expression
primary :
(expression)
| number
The data structure to store it is:
typedef boost::variant<
std::shared_ptr<exp1>,
std::shared_ptr<exp2>,
> expression
typedef boost::variant<
std::shared_ptr<prim1>,
std::shared_ptr<prim2>,
> primary
Class exp1/2 and prim1/2 are used to store the two different cases in expression and primary:
class exp1 : public BaseClass {
public :
std::shared_ptr<primary> mem1;
exp1(std::shared_ptr<primary> i1):
mem1(i1)
{}
}
For simplification, I only show exp1, while exp2 and prim1/2 are similar. In bison file, the rules and their actions are written like this :
expression :
primary {
$$= std::make_shared<expression>(std::make_shared<exp1>($1));
}
such a solution leads to two problem:
1 compiling is veeeeeeeeeeeery slow , cost almost 1 minute with g++ 4.8.4
2 run time is not very fast
I have a similar parser written in ocaml and ocamlyacc, it support very elegent specification for variant, and compile with 1 seconds, and the run speed is very similar to g++ version mentioned above.
Is there any problem in my style of using boost::variant?
==============
I change all the variant to class with constructor accepting shared_ptrs:
class ComponentBase {
};
Class VariantBase{
};
class prim1;
class prim2;
class exp1;
class exp2;
class expression : public VariantBase {
expression (shared_ptr<ComponentBase> i1):
VariantBase(i1) {}
}
class primary : public VariantBase {
primary (shared_ptr<ComponentBase> i1):
VariantBase(i1) {}
}
Then there is NO any improvement on compilation. It seems that code generated by the yacc is the source of slow.
Any suggestion?