Commit 7ce8518e authored by Simon Morlat's avatar Simon Morlat

add demo program, that demonstrate the use of belr in real parser API.

parent 99313a25
belrdir=$(includedir)/belr
belr_HEADERS = belr.hh abnf.hh grammarbuilder.hh parser.hh parser-impl.cc
EXTRA_DIST=$(belr_HEADERS)
#include "belr/abnf.hh" #include "belr/abnf.hh"
#include "belr/grammarbuilder.hh" #include "belr/grammarbuilder.hh"
#include "parser-impl.cc" #include "belr/parser-impl.cc"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <belr/parser.hh> #include <belr/parser.hh>
#include <iostream> #include <iostream>
#include "parser-impl.cc" #include "belr/parser-impl.cc"
namespace belr{ namespace belr{
......
bin_PROGRAMS=belr-parse bin_PROGRAMS=belr-parse belr-demo
belr_parse_SOURCES=belrparse.cc belr_parse_SOURCES=belrparse.cc
belr_parse_LDADD=$(top_builddir)/src/libbelr.la belr_parse_LDADD=$(top_builddir)/src/libbelr.la
belr_demo_SOURCES=belrdemo.cc
belr_demo_LDADD=$(top_builddir)/src/libbelr.la
AM_CPPFLAGS=-I$(top_srcdir)/include AM_CPPFLAGS=-I$(top_srcdir)/include
#include "belr/grammarbuilder.hh"
#include "belr/abnf.hh"
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <ctime>
#include <cstring>
#include "belr/parser-impl.cc" //this file is to be included only in the file where the parser is instanciated, for template instanciation.
using namespace::belr;
using namespace::std;
/*
* This demo program instanciates a SIP parser from the SIP grammar in a text file.
* Then it attempts to parse a SIP URI and fill URI components in our custom C++ object.
**/
/*This is our base class for all our parsed elements. It does nothing but is required for run time type identification*/
class SipElement{
public:
SipElement(){
}
//put a virtual destructor to enable polymorphism and dynamic casting.
virtual ~SipElement(){
}
};
/*this the class representing uri "other" params, per the grammar. They will be added to the SIP-URI when found.*/
class OtherParam : public SipElement{
private:
string mName;
string mValue;
public:
OtherParam(){
}
static shared_ptr<OtherParam> create(){
return make_shared<OtherParam>();
}
void setName(const string & name){
mName = name;
}
const string & getName()const{
return mName;
}
void setValue(const string &value){
mValue = value;
}
const string &getValue()const{
return mValue;
}
};
/*This is our SipUri class, representing sip uris. It has accessors for most common field, including accessing parameters*/
class SipUri : public SipElement{
private:
string mUsername;
string mHost;
string mPasswd;
int mPort;
list<shared_ptr<OtherParam>> mOtherParams;
public:
static shared_ptr<SipUri> create(){
return make_shared<SipUri>();
}
SipUri(){
mPort = 0;
}
/*follows all the setter/getters of SIP-URI fields*/
void setUsername(const string &username){
mUsername = username;
}
const string & getUsername()const{
return mUsername;
}
void setHost(const string &host){
mHost = host;
}
const string & getHost()const{
return mHost;
}
void setPasswd(const string & passwd){
mPasswd = passwd;
}
const string &getPasswd()const{
return mPasswd;
}
void setPort(int port){
mPort = port;
}
int getPort()const{
return mPort;
}
void addOtherParam(const shared_ptr<OtherParam> &params){
mOtherParams.push_back(params);
}
const list<shared_ptr<OtherParam>> & getOtherParams()const{
return mOtherParams;
}
};
int main(int argc, char *argv[]){
string uriToParse;
if (argc<2){
cerr<<argv[0]<<" <uri to parse>"<<endl;
return -1;
}
uriToParse = argv[1];
//Create a GrammarBuilder:
ABNFGrammarBuilder builder;
//construct the grammar from the grammar file, the core rules are included since required by most RFCs.
shared_ptr<Grammar> grammar=builder.createFromAbnf("sipgrammar.txt", make_shared<CoreRules>());
if (!grammar){
cerr<<"Could not build grammar from sipgrammar.txt"<<endl;
return -1;
}
//now instanciate a parser and assign it collectors and handlers
//This parser expects to build objects which are all inherited from SipElement, and that are stored as shared_ptr.
Parser<shared_ptr<SipElement>> parser(grammar);
//Now, tell our parser where to assign elements when they are found during parsing.
parser.setHandler("SIP-URI", make_fn(&SipUri::create)) //tells that whenever a SIP-URI is found, a SipUri object must be created.
->setCollector("user", make_sfn(&SipUri::setUsername)) //tells that when a "user" field is found, SipUri::setUsername() is to be called for assigning the "user"
->setCollector("host", make_sfn(&SipUri::setHost)) //tells that when host is encountered, use SipUri::setHost() to assign it to our SipUri object.
->setCollector("port", make_sfn(&SipUri::setPort)) // understood ?
->setCollector("password", make_sfn(&SipUri::setPasswd))
->setCollector("other-param", make_sfn(&SipUri::addOtherParam));
parser.setHandler("other-param", make_fn(&OtherParam::create)) //when other-param is matched, construct an OtherParam object to hold the name and value of the other-params.
->setCollector("pname", make_sfn(&OtherParam::setName))
->setCollector("pvalue", make_sfn(&OtherParam::setValue));
//now, parse the input. We have to tell the parser the root object, which is the SIP-URI in this example.
size_t parsedSize = 0;
shared_ptr<SipElement> ret = parser.parseInput("SIP-URI", uriToParse, &parsedSize);
//if a sip uri is found, the return value is non null and should cast into a SipUri object.
if (ret){
shared_ptr<SipUri> sipUri = dynamic_pointer_cast<SipUri>(ret);
//now let's print the content of uri object to make sure that its content is consistent with the input passed.
cout<<"user: "<<sipUri->getUsername()<<endl;
cout<<"passord: "<<sipUri->getPasswd()<<endl;
cout<<"host: "<<sipUri->getHost()<<endl;
cout<<"port: "<<sipUri->getPort()<<endl;
cout<<"Listing of other-params:"<<endl;
for(auto it = sipUri->getOtherParams().begin(); it != sipUri->getOtherParams().end(); ++it){
cout<<"name: "<<(*it)->getName()<<" value: "<<(*it)->getValue()<<endl;
}
}else{
cerr<<"Could not parse ["<<uriToParse<<"]"<<endl;
}
//so nice, so easy to use belr, isn't it ?
return 0;
};
...@@ -41,7 +41,7 @@ int main(int argc, char *argv[]){ ...@@ -41,7 +41,7 @@ int main(int argc, char *argv[]){
ABNFGrammarBuilder builder; ABNFGrammarBuilder builder;
shared_ptr<Grammar> grammar=make_shared<Grammar>(file); shared_ptr<Grammar> grammar=make_shared<Grammar>(file);
grammar->include(make_shared<CoreRules>()); grammar->include(make_shared<CoreRules>());
builder.createFromAbnf(file,grammar); grammar = builder.createFromAbnf(file,grammar);
if (message_file){ if (message_file){
ifstream istr(message_file); ifstream istr(message_file);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment