Commit 97a8c821 authored by Simon Morlat's avatar Simon Morlat
Browse files

templatized parser, with the base type for all parsed elements.

parent a9f7564e
...@@ -18,10 +18,10 @@ const string &Recognizer::getName()const{ ...@@ -18,10 +18,10 @@ const string &Recognizer::getName()const{
return mName; return mName;
} }
size_t Recognizer::feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t Recognizer::feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
size_t match; size_t match;
shared_ptr<HandlerContext> hctx=ctx->beginParse(shared_from_this()); shared_ptr<HandlerContextBase> hctx=ctx->beginParse(shared_from_this());
match=_feed(ctx, input, pos); match=_feed(ctx, input, pos);
if (match!=string::npos && match>0){ if (match!=string::npos && match>0){
if (0 && mName.size()>0){ if (0 && mName.size()>0){
...@@ -43,7 +43,7 @@ CharRecognizer::CharRecognizer(int to_recognize, bool caseSensitive) : mToRecogn ...@@ -43,7 +43,7 @@ CharRecognizer::CharRecognizer(int to_recognize, bool caseSensitive) : mToRecogn
} }
} }
size_t CharRecognizer::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t CharRecognizer::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
if (mCaseSensitive){ if (mCaseSensitive){
return input[pos]==mToRecognize ? 1 : string::npos; return input[pos]==mToRecognize ? 1 : string::npos;
} }
...@@ -58,10 +58,10 @@ shared_ptr<Selector> Selector::addRecognizer(const shared_ptr<Recognizer> &r){ ...@@ -58,10 +58,10 @@ shared_ptr<Selector> Selector::addRecognizer(const shared_ptr<Recognizer> &r){
return static_pointer_cast<Selector> (shared_from_this()); return static_pointer_cast<Selector> (shared_from_this());
} }
size_t Selector::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t Selector::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
size_t matched=0; size_t matched=0;
size_t bestmatch=0; size_t bestmatch=0;
shared_ptr<HandlerContext> bestBranch; shared_ptr<HandlerContextBase> bestBranch;
for (auto it=mElements.begin(); it!=mElements.end(); ++it){ for (auto it=mElements.begin(); it!=mElements.end(); ++it){
auto br=ctx->branch(); auto br=ctx->branch();
...@@ -84,7 +84,7 @@ size_t Selector::_feed(const shared_ptr<ParserContext> &ctx, const string &input ...@@ -84,7 +84,7 @@ size_t Selector::_feed(const shared_ptr<ParserContext> &ctx, const string &input
ExclusiveSelector::ExclusiveSelector(){ ExclusiveSelector::ExclusiveSelector(){
} }
size_t ExclusiveSelector::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t ExclusiveSelector::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
size_t matched=0; size_t matched=0;
for (auto it=mElements.begin(); it!=mElements.end(); ++it){ for (auto it=mElements.begin(); it!=mElements.end(); ++it){
...@@ -105,7 +105,7 @@ shared_ptr<Sequence> Sequence::addRecognizer(const shared_ptr<Recognizer> &eleme ...@@ -105,7 +105,7 @@ shared_ptr<Sequence> Sequence::addRecognizer(const shared_ptr<Recognizer> &eleme
return static_pointer_cast<Sequence>( shared_from_this()); return static_pointer_cast<Sequence>( shared_from_this());
} }
size_t Sequence::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t Sequence::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
size_t matched=0; size_t matched=0;
size_t total=0; size_t total=0;
...@@ -132,7 +132,7 @@ shared_ptr<Loop> Loop::setRecognizer(const shared_ptr<Recognizer> &element, int ...@@ -132,7 +132,7 @@ shared_ptr<Loop> Loop::setRecognizer(const shared_ptr<Recognizer> &element, int
return static_pointer_cast<Loop>(shared_from_this()); return static_pointer_cast<Loop>(shared_from_this());
} }
size_t Loop::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t Loop::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
size_t matched=0; size_t matched=0;
size_t total=0; size_t total=0;
int repeat; int repeat;
...@@ -150,7 +150,7 @@ size_t Loop::_feed(const shared_ptr<ParserContext> &ctx, const string &input, si ...@@ -150,7 +150,7 @@ size_t Loop::_feed(const shared_ptr<ParserContext> &ctx, const string &input, si
CharRange::CharRange(int begin, int end) : mBegin(begin), mEnd(end){ CharRange::CharRange(int begin, int end) : mBegin(begin), mEnd(end){
} }
size_t CharRange::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t CharRange::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
int c=input[pos]; int c=input[pos];
if (c>=mBegin && c<=mEnd) return 1; if (c>=mBegin && c<=mEnd) return 1;
return string::npos; return string::npos;
...@@ -192,7 +192,7 @@ shared_ptr<Recognizer> RecognizerPointer::getPointed(){ ...@@ -192,7 +192,7 @@ shared_ptr<Recognizer> RecognizerPointer::getPointed(){
return mRecognizer; return mRecognizer;
} }
size_t RecognizerPointer::_feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos){ size_t RecognizerPointer::_feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos){
if (mRecognizer){ if (mRecognizer){
return mRecognizer->feed(ctx, input, pos); return mRecognizer->feed(ctx, input, pos);
}else{ }else{
......
...@@ -12,16 +12,16 @@ namespace belr{ ...@@ -12,16 +12,16 @@ namespace belr{
string tolower(const string &str); string tolower(const string &str);
class ParserContext; class ParserContextBase;
class Recognizer : public enable_shared_from_this<Recognizer>{ class Recognizer : public enable_shared_from_this<Recognizer>{
public: public:
void setName(const string &name); void setName(const string &name);
const string &getName()const; const string &getName()const;
size_t feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); size_t feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
protected: protected:
Recognizer(); Recognizer();
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos)=0; virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos)=0;
string mName; string mName;
}; };
...@@ -29,7 +29,7 @@ class CharRecognizer : public Recognizer{ ...@@ -29,7 +29,7 @@ class CharRecognizer : public Recognizer{
public: public:
CharRecognizer(int to_recognize, bool caseSensitive=false); CharRecognizer(int to_recognize, bool caseSensitive=false);
private: private:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
int mToRecognize; int mToRecognize;
bool mCaseSensitive; bool mCaseSensitive;
}; };
...@@ -39,7 +39,7 @@ class CharRange : public Recognizer{ ...@@ -39,7 +39,7 @@ class CharRange : public Recognizer{
public: public:
CharRange(int begin, int end); CharRange(int begin, int end);
private: private:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
int mBegin,mEnd; int mBegin,mEnd;
}; };
...@@ -48,7 +48,7 @@ public: ...@@ -48,7 +48,7 @@ public:
Selector(); Selector();
shared_ptr<Selector> addRecognizer(const shared_ptr<Recognizer> &element); shared_ptr<Selector> addRecognizer(const shared_ptr<Recognizer> &element);
protected: protected:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
list<shared_ptr<Recognizer>> mElements; list<shared_ptr<Recognizer>> mElements;
}; };
...@@ -57,7 +57,7 @@ class ExclusiveSelector : public Selector{ ...@@ -57,7 +57,7 @@ class ExclusiveSelector : public Selector{
public: public:
ExclusiveSelector(); ExclusiveSelector();
private: private:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
}; };
class Sequence : public Recognizer{ class Sequence : public Recognizer{
...@@ -65,7 +65,7 @@ public: ...@@ -65,7 +65,7 @@ public:
Sequence(); Sequence();
shared_ptr<Sequence> addRecognizer(const shared_ptr<Recognizer> &element); shared_ptr<Sequence> addRecognizer(const shared_ptr<Recognizer> &element);
private: private:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
list<shared_ptr<Recognizer>> mElements; list<shared_ptr<Recognizer>> mElements;
}; };
...@@ -74,7 +74,7 @@ public: ...@@ -74,7 +74,7 @@ public:
Loop(); Loop();
shared_ptr<Loop> setRecognizer(const shared_ptr<Recognizer> &element, int min=0, int max=-1); shared_ptr<Loop> setRecognizer(const shared_ptr<Recognizer> &element, int min=0, int max=-1);
private: private:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
shared_ptr<Recognizer> mRecognizer; shared_ptr<Recognizer> mRecognizer;
int mMin, mMax; int mMin, mMax;
}; };
...@@ -100,7 +100,7 @@ public: ...@@ -100,7 +100,7 @@ public:
shared_ptr<Recognizer> getPointed(); shared_ptr<Recognizer> getPointed();
void setPointed(const shared_ptr<Recognizer> &r); void setPointed(const shared_ptr<Recognizer> &r);
private: private:
virtual size_t _feed(const shared_ptr<ParserContext> &ctx, const string &input, size_t pos); virtual size_t _feed(const shared_ptr<ParserContextBase> &ctx, const string &input, size_t pos);
shared_ptr<Recognizer> mRecognizer; shared_ptr<Recognizer> mRecognizer;
}; };
......
#include "abnf.hh" #include "abnf.hh"
#include "grammarbuilder.hh" #include "grammarbuilder.hh"
#include "parser-impl.cc"
#include <iostream> #include <iostream>
......
...@@ -15,7 +15,7 @@ private: ...@@ -15,7 +15,7 @@ private:
void addRule(void *list, void *rule); void addRule(void *list, void *rule);
void *createRuleList(); void *createRuleList();
void *createRule(); void *createRule();
Parser mParser; Parser<void*> mParser;
}; };
} }
......
#include "parser.hh"
#include <iostream>
#include <algorithm>
namespace belr{
template <typename _parserElementT>
void Assignment<_parserElementT>::invoke(_parserElementT parent, const string &input){
if (mChild){
shared_ptr<ParserCollector<_parserElementT,_parserElementT>> cc=dynamic_pointer_cast<ParserCollector<_parserElementT,_parserElementT>>(mCollector);
if (cc){
cc->invoke(parent, mChild->realize(input));
}
}else{
string value=input.substr(mBegin, mCount);
shared_ptr<ParserCollector<_parserElementT,const string&>> cc1=dynamic_pointer_cast<ParserCollector<_parserElementT,const string&>>(mCollector);
if (cc1){
cc1->invoke(parent, value);
return;
}
shared_ptr<ParserCollector<_parserElementT,const char*>> cc2=dynamic_pointer_cast<ParserCollector<_parserElementT,const char*>>(mCollector);
if (cc2){
cc2->invoke(parent, value.c_str());
return;
}
shared_ptr<ParserCollector<_parserElementT,int>> cc3=dynamic_pointer_cast<ParserCollector<_parserElementT,int>>(mCollector);
if (cc3){
cc3->invoke(parent, atoi(value.c_str()));
return;
}
}
}
template <typename _parserElementT>
ParserContext<_parserElementT>::ParserContext(Parser<_parserElementT> &parser) : mParser(parser){
}
template <typename _parserElementT>
shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>::_beginParse(const shared_ptr<Recognizer> &rec){
shared_ptr<HandlerContext<_parserElementT>> ctx;
auto it=mParser.mHandlers.find(rec->getName());
if (it!=mParser.mHandlers.end()){
ctx=(*it).second->createContext();
mHandlerStack.push_back(ctx);
}
return ctx;
}
template <typename _parserElementT>
void ParserContext<_parserElementT>::_endParse(const shared_ptr<Recognizer> &rec, const shared_ptr<HandlerContext<_parserElementT>> &ctx, const string &input, size_t begin, size_t count){
if (ctx){
mHandlerStack.pop_back();
}
if (!mHandlerStack.empty()){
/*assign object to parent */
mHandlerStack.back()->setChild(rec->getName(), begin, count, ctx);
}else{
/*no parent, this is our root object*/
mRoot=ctx;
}
}
template <typename _parserElementT>
_parserElementT ParserContext<_parserElementT>::createRootObject(const string &input){
return mRoot ? mRoot->realize(input) : NULL;
}
template <typename _parserElementT>
shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>::_branch(){
shared_ptr<HandlerContext<_parserElementT>> ret=mHandlerStack.back()->branch();
mHandlerStack.push_back(ret);
return ret;
}
template <typename _parserElementT>
void ParserContext<_parserElementT>::_merge(const shared_ptr<HandlerContext<_parserElementT>> &other){
if (mHandlerStack.back()!=other){
cerr<<"The branch being merged is not the last one of the stack !"<<endl;
abort();
}
mHandlerStack.pop_back();
return mHandlerStack.back()->merge(other);
}
template <typename _parserElementT>
void ParserContext<_parserElementT>::_removeBranch(const shared_ptr<HandlerContext<_parserElementT>> &other){
auto it=find(mHandlerStack.rbegin(), mHandlerStack.rend(),other);
if (it==mHandlerStack.rend()){
cerr<<"A branch could not be found in the stack while removing it !"<<endl;
abort();
}else{
advance(it,1);
mHandlerStack.erase(it.base());
}
}
template <typename _parserElementT>
shared_ptr<HandlerContextBase> ParserContext<_parserElementT>::beginParse(const shared_ptr<Recognizer> &rec){
return static_pointer_cast<HandlerContext<_parserElementT>>(_beginParse(rec));
}
template <typename _parserElementT>
void ParserContext<_parserElementT>::endParse(const shared_ptr<Recognizer> &rec, const shared_ptr<HandlerContextBase> &ctx, const string &input, size_t begin, size_t count){
_endParse(rec,static_pointer_cast<HandlerContext<_parserElementT>>(ctx), input, begin, count);
}
template <typename _parserElementT>
shared_ptr<HandlerContextBase> ParserContext<_parserElementT>::branch(){
return static_pointer_cast<HandlerContext<_parserElementT>>(_branch());
}
template <typename _parserElementT>
void ParserContext<_parserElementT>::merge(const shared_ptr<HandlerContextBase> &other){
_merge(static_pointer_cast<HandlerContext<_parserElementT>>(other));
}
template <typename _parserElementT>
void ParserContext<_parserElementT>::removeBranch(const shared_ptr<HandlerContextBase> &other){
_removeBranch(static_pointer_cast<HandlerContext<_parserElementT>>(other));
}
template <typename _parserElementT>
shared_ptr<HandlerContext<_parserElementT>> ParserHandler<_parserElementT>::createContext(){
return make_shared<HandlerContext<_parserElementT>>(this->shared_from_this());
}
template <typename _parserElementT>
Parser<_parserElementT>::Parser(const shared_ptr<Grammar> &grammar) : mGrammar(grammar){
if (!mGrammar->isComplete()){
cerr<<"Grammar not complete, aborting."<<endl;
return;
}
}
template <typename _parserElementT>
_parserElementT Parser<_parserElementT>::parseInput(const string &rulename, const string &input, size_t *parsed_size){
size_t parsed;
shared_ptr<Recognizer> rec=mGrammar->getRule(rulename);
auto pctx=make_shared<ParserContext<_parserElementT>>(*this);
parsed=rec->feed(pctx, input, 0);
if (parsed_size) *parsed_size=parsed;
return pctx->createRootObject(input);
}
}
#include <parser.hh> #include <parser.hh>
#include <iostream> #include <iostream>
#include <algorithm>
namespace belr{ namespace belr{
CollectorBase::~CollectorBase(){ CollectorBase::~CollectorBase(){
} }
void Assignment::invoke(void *parent, const string &input){
if (mChild){
shared_ptr<ParserCollector<void*>> cc=dynamic_pointer_cast<ParserCollector<void*>>(mCollector);
if (cc){
cc->invoke(parent, mChild->realize(input));
}
}else{
string value=input.substr(mBegin, mCount);
shared_ptr<ParserCollector<const string&>> cc1=dynamic_pointer_cast<ParserCollector<const string&>>(mCollector);
if (cc1){
cc1->invoke(parent, value);
return;
}
shared_ptr<ParserCollector<const char*>> cc2=dynamic_pointer_cast<ParserCollector<const char*>>(mCollector);
if (cc2){
cc2->invoke(parent, value.c_str());
return;
}
shared_ptr<ParserCollector<int>> cc3=dynamic_pointer_cast<ParserCollector<int>>(mCollector);
if (cc3){
cc3->invoke(parent, atoi(value.c_str()));
return;
}
}
}
ParserContext::ParserContext(Parser &parser) : mParser(parser){
}
shared_ptr<HandlerContext> ParserContext::beginParse(const shared_ptr<Recognizer> &rec){
shared_ptr<HandlerContext> ctx;
auto it=mParser.mHandlers.find(rec->getName());
if (it!=mParser.mHandlers.end()){
ctx=(*it).second->createContext();
mHandlerStack.push_back(ctx);
}
return ctx;
}
void ParserContext::endParse(const shared_ptr<Recognizer> &rec, const shared_ptr<HandlerContext> &ctx, const string &input, size_t begin, size_t count){
if (ctx){
mHandlerStack.pop_back();
}
if (!mHandlerStack.empty()){
/*assign object to parent */
mHandlerStack.back()->setChild(rec->getName(), begin, count, ctx);
}else{
/*no parent, this is our root object*/
mRoot=ctx;
}
}
void *ParserContext::createRootObject(const string &input){
return mRoot ? mRoot->realize(input) : NULL;
}
shared_ptr<HandlerContext> ParserContext::branch(){
shared_ptr<HandlerContext> ret=mHandlerStack.back()->branch();
mHandlerStack.push_back(ret);
return ret;
}
void ParserContext::merge(const shared_ptr<HandlerContext> &other){
if (mHandlerStack.back()!=other){
cerr<<"The branch being merged is not the last one of the stack !"<<endl;
abort();
}
mHandlerStack.pop_back();
return mHandlerStack.back()->merge(other);
}
void ParserContext::removeBranch(const shared_ptr<HandlerContext> &other){
auto it=find(mHandlerStack.rbegin(), mHandlerStack.rend(),other);
if (it==mHandlerStack.rend()){
cerr<<"A branch could not be found in the stack while removing it !"<<endl;
abort();
}else{
advance(it,1);
mHandlerStack.erase(it.base());
}
}
shared_ptr<HandlerContext> ParserHandler::createContext(){
return make_shared<HandlerContext>(shared_from_this());
}
Parser::Parser(const shared_ptr<Grammar> &grammar) : mGrammar(grammar){
if (!mGrammar->isComplete()){
cerr<<"Grammar not complete, aborting."<<endl;
return;
}
}
void * Parser::parseInput(const string &rulename, const string &input, size_t *parsed_size){
size_t parsed;
shared_ptr<Recognizer> rec=mGrammar->getRule(rulename);
shared_ptr<ParserContext> pctx=make_shared<ParserContext>(*this);
parsed=rec->feed(pctx, input, 0);
if (parsed_size) *parsed_size=parsed;
return pctx->createRootObject(input);
}
}//end of namespace }//end of namespace
\ No newline at end of file
...@@ -12,113 +12,138 @@ public: ...@@ -12,113 +12,138 @@ public:
virtual ~CollectorBase(); virtual ~CollectorBase();
}; };
template <typename _valueT> template <typename _parserElementT, typename _valueT>
class ParserCollector : public CollectorBase{ class ParserCollector : public CollectorBase{
public: public:
ParserCollector(const function<void (void *, _valueT)> &fn) : mFunc(fn){ ParserCollector(const function<void (_parserElementT , _valueT)> &fn) : mFunc(fn){
} }
function<void (void *, _valueT)> mFunc; function<void (_parserElementT, _valueT)> mFunc;
void invoke(void *obj, _valueT value){ void invoke(_parserElementT obj, _valueT value){
mFunc(obj,value); mFunc(obj,value);
} }
}; };
template <typename _parserElementT>
class HandlerContext; class HandlerContext;
class ParserHandler : public enable_shared_from_this<ParserHandler>{ template <typename _parserElementT>
class ParserHandler : public enable_shared_from_this<ParserHandler<_parserElementT>>{
public: public:
friend class HandlerContext; friend class HandlerContext<_parserElementT>;
ParserHandler(const function<void * ()> &create) ParserHandler(const function<_parserElementT ()> &create)
: mHandlerCreateFunc(create){ : mHandlerCreateFunc(create){
} }
template <typename _valueT> template <typename _valueT>
shared_ptr<ParserHandler> setCollector(const string &child_rule_name, function<void (void * , _valueT)> fn){ shared_ptr<ParserHandler<_parserElementT>> setCollector(const string &child_rule_name, function<void (_parserElementT , _valueT)> fn){
mCollectors[child_rule_name]=make_shared<ParserCollector<_valueT>>(fn); mCollectors[child_rule_name]=make_shared<ParserCollector<_parserElementT,_valueT>>(fn);
return shared_from_this(); return this->shared_from_this();
} }
void *invoke(){ _parserElementT invoke(){
return mHandlerCreateFunc(); return mHandlerCreateFunc();
} }
shared_ptr<HandlerContext> createContext(); shared_ptr<HandlerContext<_parserElementT>> createContext();
private: private:
function<void * ()> mHandlerCreateFunc; function<_parserElementT ()> mHandlerCreateFunc;
map<string, shared_ptr<CollectorBase> > mCollectors; map<string, shared_ptr<CollectorBase> > mCollectors;
}; };
template <typename _parserElementT>