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
belr_HEADERS = belr.hh abnf.hh grammarbuilder.hh parser.hh
#include "belr/abnf.hh"
#include "belr/grammarbuilder.hh"
#include ""
#include "belr/"
#include <iostream>
#include <fstream>
......@@ -2,7 +2,7 @@
#include <belr/parser.hh>
#include <iostream>
#include ""
#include "belr/"
namespace belr{
bin_PROGRAMS=belr-parse belr-demo
#include "belr/grammarbuilder.hh"
#include "belr/abnf.hh"
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <ctime>
#include <cstring>
#include "belr/" //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{
//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{
string mName;
string mValue;
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{
string mUsername;
string mHost;
string mPasswd;
int mPort;
list<shared_ptr<OtherParam>> mOtherParams;
static shared_ptr<SipUri> create(){
return make_shared<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){
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;
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[]){
ABNFGrammarBuilder builder;
shared_ptr<Grammar> grammar=make_shared<Grammar>(file);
grammar = builder.createFromAbnf(file,grammar);
if (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