Originally Posted by
King Mir
Certainly existing tools are not perfect for every use, but writing a parser for a domain specific language is a pretty common problem, and there are tools out there to do it easily.
Well, that does not help me much while trying to learn the theory.
I may try to create such a generator based on my own code in future, though.
Anyway, here is the revised design (code not rigorously tested yet..).
It is few steps forward(much simpler, same object to work on arbitrary strings, etc) and a few back back from the original(uses the input iterator a a reference,huge inheritance tree ..etc).
Also, it still uses std::string iterators. I'm having some trouble combining templates and inheritance..but they should go away after a few hello world experiments.
The giant looks like this
Code:
ParsingExpression
Atomic
Terminal
Empty
SingleChar
Range
NonTerminal
Compound
Sequence
Choice
ZeroOrMore
OneOrMore
Optional
AndPredicate
NotPredicate
I'm describing it using 4 classes, the base, and three of the leaves.
Code:
//Base
typedef std::string::iterator sit;
class ParsingExpression
{
public:
virtual bool operator()(sit& begin,sit end)=0;
};
Code:
//Matching ranges
class Range:public Terminal
{
public:
Range(char start_,char stop_):start(start_),stop(stop_){}
bool operator()(sit& begin,sit end)
{
char i = *begin;
if(i>=start&&i<=stop)
{
++begin;
return true;
}
else return false;
}
private:
char start;
char stop;
};
Code:
//Sequence
class Sequence:public Compound
{
public:
// Sequence(std::vector<ParsingExpression*> s):subjects(s){} //Should I let a 'friendly' factory worry about this?
bool operator()(sit& begin,sit end)
{
sit ori = begin;
bool result=true;
for(int i=0;i<subjects.size() && result && begin!=end;++i)
{
result = subjects[i]->operator()(begin,end);
}
if(!result) begin = ori;
return result;
}
private:
std::vector<ParsingExpression*> subjects;
};
//Priority Choice
class Choice:public Compound
{
public:
bool operator()(sit& begin,sit end)
{
for(auto e:subjects)
{
if(e->operator()(begin,end))
return true;
}
};
private:
std::vector<ParsingExpression*> subjects;
};