parser-impl.cc 11.7 KB
Newer Older
1

2
#include "belr/parser.hh"
3 4
#include <iostream>
#include <algorithm>
5
//#include <chrono>
6
#include <ctime>
7 8 9

namespace belr{

10 11 12 13 14 15 16 17 18 19
template <class T, class U>
T universal_pointer_cast(const shared_ptr<U>& sp){
	return static_pointer_cast<typename T::element_type>(sp);
}

template <class T, class U>
T universal_pointer_cast(U * p){
	return static_cast<T>(p);
}
	
20 21 22 23 24 25
template <typename _parserElementT>
AbstractCollector<_parserElementT>::~AbstractCollector(){
}

template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
void ParserCollector<_derivedParserElementT,_parserElementT, _valueT>::invoke(_parserElementT obj, _valueT value){
26 27 28 29 30 31 32
	mFunc(universal_pointer_cast<_derivedParserElementT>(obj),value);
}

template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
void ParserCollector<_derivedParserElementT,_parserElementT, _valueT>::invokeWithChild(_parserElementT obj, _parserElementT child){
	cerr<<"We should never be called in ParserCollector<_derivedParserElementT,_parserElementT, _valueT>::invokeWithChild(_parserElementT obj, _parserElementT child)"<<endl;
	abort();
33 34 35
}

template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
36 37 38 39 40 41 42 43
void ParserChildCollector<_derivedParserElementT,_parserElementT, _valueT>::invokeWithChild(_parserElementT obj, _parserElementT value){
	mFunc(universal_pointer_cast<_derivedParserElementT>(obj),universal_pointer_cast<typename decay<_valueT>::type>(value));
}

template <typename _derivedParserElementT, typename _parserElementT, typename _valueT>
void ParserChildCollector<_derivedParserElementT,_parserElementT, _valueT>::invoke(_parserElementT obj, _valueT value){
	cerr<<"We should never be called in ParserChildCollector<_derivedParserElementT,_parserElementT, _valueT>::invoke(_parserElementT obj, _valueT value)"<<endl;
	abort();
44 45
}

46 47 48
template <typename _parserElementT>
void Assignment<_parserElementT>::invoke(_parserElementT parent, const string &input){
	if (mChild){
Simon Morlat's avatar
Simon Morlat committed
49
		mCollector->invokeWithChild(parent, mChild->realize(input,mBegin,mCount));
50 51
	}else{
		string value=input.substr(mBegin, mCount);
52
		CollectorBase<_parserElementT,const string&>* cc1=dynamic_cast<CollectorBase<_parserElementT,const string&>*>(mCollector);
53 54 55 56
		if (cc1){
			cc1->invoke(parent, value);
			return;
		}
57
		CollectorBase<_parserElementT,const char*>* cc2=dynamic_cast<CollectorBase<_parserElementT,const char*>*>(mCollector);
58 59 60 61
		if (cc2){
			cc2->invoke(parent, value.c_str());
			return;
		}
62
		CollectorBase<_parserElementT,int> *cc3=dynamic_cast<CollectorBase<_parserElementT,int>*>(mCollector);
63 64 65 66 67 68 69
		if (cc3){
			cc3->invoke(parent, atoi(value.c_str()));
			return;
		}
	}
}

Simon Morlat's avatar
Simon Morlat committed
70 71

//
Simon Morlat's avatar
Simon Morlat committed
72
// HandlerContext template class implementation
Simon Morlat's avatar
Simon Morlat committed
73 74 75 76
//

template <typename _parserElementT>
HandlerContext<_parserElementT>::HandlerContext(const shared_ptr<ParserHandlerBase<_parserElementT>> &handler) : 
77
	mHandler(*handler.get()){
Simon Morlat's avatar
Simon Morlat committed
78 79 80
}

template <typename _parserElementT>
81
void HandlerContext<_parserElementT>::setChild(unsigned int subrule_id, size_t begin, size_t count, const shared_ptr<HandlerContext<_parserElementT>> &child){
82
	auto collector=mHandler.getCollector(subrule_id);
Simon Morlat's avatar
Simon Morlat committed
83 84
	if (collector){
		mAssignments.push_back(Assignment<_parserElementT>(collector, begin, count, child));
Simon Morlat's avatar
Simon Morlat committed
85 86 87 88 89
	}
}

template <typename _parserElementT>
_parserElementT HandlerContext<_parserElementT>::realize(const string &input, size_t begin, size_t count){
90
	_parserElementT ret=mHandler.invoke(input, begin, count);
Simon Morlat's avatar
Simon Morlat committed
91 92 93 94 95 96 97 98
	for (auto it=mAssignments.begin(); it!=mAssignments.end(); ++it){
		(*it).invoke(ret,input);
	}
	return ret;
}

template <typename _parserElementT>
shared_ptr<HandlerContext<_parserElementT>> HandlerContext<_parserElementT>::branch(){
99
	return mHandler.createContext();
Simon Morlat's avatar
Simon Morlat committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}

template <typename _parserElementT>
void HandlerContext<_parserElementT>::merge(const shared_ptr<HandlerContext<_parserElementT>> &other){
	for (auto it=other->mAssignments.begin();it!=other->mAssignments.end();++it){
		mAssignments.emplace_back(*it);
	}
}

template <typename _parserElementT>
size_t HandlerContext<_parserElementT>::getLastIterator()const{
	return mAssignments.size();
}

template <typename _parserElementT>
void HandlerContext<_parserElementT>::undoAssignments(size_t pos){
	mAssignments.erase(mAssignments.begin()+pos,mAssignments.end());
}

119 120 121 122 123 124
template <typename _parserElementT>
void HandlerContext< _parserElementT >::recycle(){
	mAssignments.clear();
	mHandler.releaseContext(static_pointer_cast<HandlerContext< _parserElementT >>(shared_from_this()));
}

Simon Morlat's avatar
Simon Morlat committed
125 126 127 128 129
//
// ParserHandlerBase template class implementation
//

template <typename _parserElementT>
130
ParserHandlerBase<_parserElementT>::ParserHandlerBase(const Parser<_parserElementT> &parser, const string &name) : mParser(parser), mRulename(tolower(name)), mCachedContext(NULL) {
Simon Morlat's avatar
Simon Morlat committed
131 132 133 134
}

template <typename _parserElementT>
void ParserHandlerBase<_parserElementT>::installCollector(const string &rulename, const shared_ptr<AbstractCollector<_parserElementT>> &collector){
135 136 137 138 139 140
	shared_ptr<Recognizer> rec=mParser.mGrammar->findRule(rulename);
	if (!rec){
		cerr<<"There is no rule '"<<rulename<<"' in the grammar."<<endl;
		return;
	}
	mCollectors[rec->getId()]=collector;
Simon Morlat's avatar
Simon Morlat committed
141 142 143
}

template <typename _parserElementT>
144 145
const shared_ptr<AbstractCollector<_parserElementT>> & ParserHandlerBase<_parserElementT>::getCollector(unsigned int rule_id)const{
	auto it=mCollectors.find(rule_id);
Simon Morlat's avatar
Simon Morlat committed
146
	if (it!=mCollectors.end()) return (*it).second;
Simon Morlat's avatar
Simon Morlat committed
147
	return mParser.mNullCollector;
Simon Morlat's avatar
Simon Morlat committed
148 149
}

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
template <typename _parserElementT>
void ParserHandlerBase< _parserElementT >::releaseContext(const shared_ptr<HandlerContext<_parserElementT>> &ctx){
	mCachedContext=ctx;
}

template <typename _parserElementT>
shared_ptr<HandlerContext<_parserElementT>> ParserHandlerBase<_parserElementT>::createContext(){
	if (mCachedContext) {
		shared_ptr<HandlerContext<_parserElementT>> ret=mCachedContext;
		mCachedContext.reset();
		return ret;
	}
	return make_shared<HandlerContext<_parserElementT>>(this->shared_from_this());
}

Simon Morlat's avatar
Simon Morlat committed
165 166 167 168
//
// ParserHandler template implementation
//

169
template <typename _derivedParserElementT, typename _parserElementT>
Simon Morlat's avatar
Simon Morlat committed
170 171 172 173
_parserElementT ParserHandler<_derivedParserElementT,_parserElementT>::invoke(const string &input, size_t begin, size_t count){
	if (mHandlerCreateFunc)
		return universal_pointer_cast<_parserElementT>(mHandlerCreateFunc());
	if (mHandlerCreateDebugFunc)
Simon Morlat's avatar
Simon Morlat committed
174
		return universal_pointer_cast<_parserElementT>(mHandlerCreateDebugFunc(this->getRulename(), input.substr(begin, count)));
Simon Morlat's avatar
Simon Morlat committed
175
	return NULL;
176 177
}

178 179 180 181 182

//
// ParserContext template class implementation
//

183
template <typename _parserElementT>
184
ParserContext<_parserElementT>::ParserContext(Parser<_parserElementT> &parser) : mParser(parser) {
185 186 187
}

template <typename _parserElementT>
188
void ParserContext<_parserElementT>::_beginParse(ParserLocalContext & lctx, const shared_ptr<Recognizer> &rec){
189
	shared_ptr<HandlerContextBase> ctx;
190

191
	auto h=mParser.getHandler(rec->getId());
Simon Morlat's avatar
Simon Morlat committed
192 193
	if (h){
		ctx=h->createContext();
194
		mHandlerStack.push_back(static_pointer_cast<HandlerContext<_parserElementT>>(ctx));
195
	}
196
	lctx.set(ctx,rec,mHandlerStack.back()->getLastIterator());
197 198 199
}

template <typename _parserElementT>
200
void ParserContext<_parserElementT>::_endParse(const ParserLocalContext &localctx, const string &input, size_t begin, size_t count){
201
	if (localctx.mHandlerContext){
202
		mHandlerStack.pop_back();
203 204 205
		if (count!=string::npos && count>0){
			if (!mHandlerStack.empty()){
				/*assign object to parent */
206
				mHandlerStack.back()->setChild(localctx.mRecognizer->getId(), begin, count, 
207 208 209 210 211 212
					static_pointer_cast<HandlerContext< _parserElementT >> (localctx.mHandlerContext));
				
			}else{
				/*no parent, this is our root object*/
				mRoot=static_pointer_cast<HandlerContext< _parserElementT >>(localctx.mHandlerContext);
			}
213 214 215
		}else{
			//no match
			static_pointer_cast<HandlerContext< _parserElementT >>(localctx.mHandlerContext)->recycle();
216 217 218 219
		}
	}else{
		if (count!=string::npos && count>0){
			/*assign string to parent */
220 221
			if (localctx.mRecognizer->getId()!=0)
				mHandlerStack.back()->setChild(localctx.mRecognizer->getId(), begin, count, NULL);
222
		}else{
223
			mHandlerStack.back()->undoAssignments(localctx.mAssignmentPos);
224
		}
225 226 227 228 229
	}
}

template <typename _parserElementT>
_parserElementT ParserContext<_parserElementT>::createRootObject(const string &input){
Simon Morlat's avatar
Simon Morlat committed
230
	 return mRoot ? mRoot->realize(input,0,input.size()) : NULL;
231 232 233 234
}

template <typename _parserElementT>
shared_ptr<HandlerContext<_parserElementT>> ParserContext<_parserElementT>::_branch(){
Simon Morlat's avatar
Simon Morlat committed
235 236 237
	if (mHandlerStack.empty()){
		cerr<<"Cannot branch while stack is empty"<<endl;
	}
238 239 240 241 242 243 244 245 246 247 248 249
	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();
250 251
	mHandlerStack.back()->merge(other);
	other->recycle();
252 253 254 255 256 257 258 259 260 261 262 263
}

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());
	}
264
	other->recycle();
265 266 267
}

template <typename _parserElementT>
268 269
void ParserContext<_parserElementT>::beginParse(ParserLocalContext &ctx, const shared_ptr<Recognizer> &rec){
	_beginParse(ctx, rec);
270 271 272
}

template <typename _parserElementT>
273 274
void ParserContext<_parserElementT>::endParse(const ParserLocalContext &localctx, const string &input, size_t begin, size_t count){
	_endParse(localctx, input, begin, count);
275 276 277 278
}

template <typename _parserElementT>
shared_ptr<HandlerContextBase> ParserContext<_parserElementT>::branch(){
279
	return _branch();
280 281 282 283 284 285 286 287 288 289 290 291
}

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));
}

Simon Morlat's avatar
Simon Morlat committed
292 293 294 295
//
// Parser template class implementation
//

296
template <typename _parserElementT>
297
Parser<_parserElementT>::Parser(const shared_ptr<Grammar> &grammar) : mGrammar(grammar) {
298 299 300 301 302 303
	if (!mGrammar->isComplete()){
		cerr<<"Grammar not complete, aborting."<<endl;
		return;
	}
}

Simon Morlat's avatar
Simon Morlat committed
304
template <typename _parserElementT>
305 306
shared_ptr<ParserHandlerBase<_parserElementT>> &Parser<_parserElementT>::getHandler(unsigned int rule_id){
	auto it=mHandlers.find(rule_id);
Simon Morlat's avatar
Simon Morlat committed
307
	if (it==mHandlers.end()) return mNullHandler;
Simon Morlat's avatar
Simon Morlat committed
308 309 310 311 312
	return (*it).second;
}

template <typename _parserElementT>
void Parser<_parserElementT>::installHandler(const shared_ptr<ParserHandlerBase<_parserElementT>> &handler){
313 314 315 316 317 318
	shared_ptr<Recognizer> rec=mGrammar->findRule(handler->getRulename());
	if (rec==NULL){
		cerr<<"There is no rule '"<<handler->getRulename()<<"' in the grammar."<<endl;
		return;
	}
	mHandlers[rec->getId()]=handler;
Simon Morlat's avatar
Simon Morlat committed
319 320
}

321 322 323 324 325 326
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);
	
Simon Morlat's avatar
Simon Morlat committed
327
	//auto t_start = std::chrono::high_resolution_clock::now();
328
	parsed=rec->feed(pctx, input, 0);
Simon Morlat's avatar
Simon Morlat committed
329 330
	//auto t_end = std::chrono::high_resolution_clock::now();
	//cout<<"Recognition done in "<<std::chrono::duration<double, std::milli>(t_end-t_start).count()<<" milliseconds"<<endl;
331
	if (parsed_size) *parsed_size=parsed;
332 333
	auto ret= pctx->createRootObject(input);
	return ret;
334 335 336
}

}