Commit 8654645f authored by Simon Morlat's avatar Simon Morlat

Add save method to Grammar.

parent 21a8a58d
......@@ -23,6 +23,7 @@
#include <map>
#include <memory>
#include <string>
#include <fstream>
// =============================================================================
......@@ -68,10 +69,11 @@ public:
bool getTransitionMap(TransitionMap *mask);
void optimize();
void optimize(int recursionLevel);
void serialize(std::ofstream &fstr);
protected:
Recognizer() = default;
virtual void _serialize(std::ofstream &fstr) = 0;
void writeInt(std::ofstream &fstr, int number);
/*returns true if the transition map is complete, false otherwise*/
virtual bool _getTransitionMap(TransitionMap *mask);
virtual void _optimize(int recursionLevel)=0;
......@@ -81,6 +83,17 @@ protected:
unsigned int mId = 0;
};
enum RecognizerTypeId{
CharRecognizerId = 1,
SelectorId,
ExclusiveSelectorId,
SequenceId,
LoopId,
CharRangeId,
LiteralId,
PointerId
};
class CharRecognizer : public Recognizer{
public:
CharRecognizer(int to_recognize, bool caseSensitive=false);
......@@ -88,6 +101,7 @@ public:
private:
size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override;
void _optimize(int recursionLevel) override;
virtual void _serialize(std::ofstream &fstr) override;
int mToRecognize;
bool mCaseSensitive;
......@@ -101,6 +115,7 @@ protected:
void _optimize(int recursionLevel) override;
size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override;
bool _getTransitionMap(TransitionMap *mask) override;
virtual void _serialize(std::ofstream &fstr) override;
size_t _feedExclusive(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos);
......@@ -121,6 +136,7 @@ public:
std::shared_ptr<Sequence> addRecognizer(const std::shared_ptr<Recognizer> &element);
protected:
virtual void _serialize(std::ofstream &fstr) override;
void _optimize(int recursionLevel) override;
private:
......@@ -136,6 +152,7 @@ public:
std::shared_ptr<Loop> setRecognizer(const std::shared_ptr<Recognizer> &element, int min=0, int max=-1);
protected:
virtual void _serialize(std::ofstream &fstr) override;
void _optimize(int recursionLevel) override;
private:
......@@ -161,6 +178,7 @@ public:
CharRange(int begin, int end);
private:
virtual void _serialize(std::ofstream &fstr) override;
void _optimize(int recursionLevel) override;
size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override;
......@@ -176,6 +194,7 @@ public:
private:
void _optimize(int recursionLevel) override;
virtual void _serialize(std::ofstream &fstr) override;
size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override;
std::string mLiteral;
......@@ -195,6 +214,7 @@ public:
private:
void _optimize(int recursionLevel) override;
virtual void _serialize(std::ofstream &fstr) override;
size_t _feed(const std::shared_ptr<ParserContextBase> &ctx, const std::string &input, size_t pos) override;
std::shared_ptr<Recognizer> mRecognizer;
......@@ -272,6 +292,10 @@ public:
* Return the number of rules in this grammar.
**/
int getNumRules()const;
/**
* Save the grammar into a binary file.
**/
int save(const std::string &filename);
private:
void assignRule(const std::string &name, const std::shared_ptr<Recognizer> &rule);
void _extendRule(const std::string &name, const std::shared_ptr<Recognizer> &rule);
......
......@@ -23,6 +23,7 @@
#include <functional>
#include <iostream>
#include <vector>
#include <sstream>
#include "belr.h"
......
......@@ -66,6 +66,36 @@ void Recognizer::setName(const std::string& name){
mId=++id_base;
}
void Recognizer::serialize(std::ofstream& fstr){
RecognizerTypeId tid = CharRecognizerId;
if (typeid(*this) == typeid(CharRecognizer)) tid = CharRecognizerId;
else if (typeid(*this) == typeid(Selector)) tid = SelectorId;
else if (typeid(*this) == typeid(Loop)) tid = LoopId;
else if (typeid(*this) == typeid(ExclusiveSelector)) tid = ExclusiveSelectorId;
else if (typeid(*this) == typeid(CharRange)) tid = CharRangeId;
else if (typeid(*this) == typeid(Literal)) tid = LiteralId;
else if (typeid(*this) == typeid(Sequence)) tid = SequenceId;
else if (typeid(*this) == typeid(RecognizerPointer)) tid = PointerId;
else bctbx_fatal("Unsupported Recognizer derived type.");
unsigned char type_byte = (unsigned char)tid;
//write the type
fstr.write((char*)&type_byte, 1);
//write the id if any followed by name, or a single zero byte if not.
if (mId > 0){
writeInt(fstr, mId);
fstr<<mName;
fstr.write("", 1);
}
//then invoked derived class serialization
_serialize(fstr);
}
void Recognizer::writeInt(std::ofstream &fstr, int number){
int tmp = htonl(number);
fstr.write((char*)&tmp, sizeof(tmp));
}
const string &Recognizer::getName()const{
return mName;
}
......@@ -149,6 +179,12 @@ void CharRecognizer::_optimize(int recursionLevel){
}
void CharRecognizer::_serialize(std::ofstream &fstr){
unsigned char charToRecognize = (unsigned char)mToRecognize;
fstr.write((char*)&charToRecognize, 1);
fstr.write((char*)&mCaseSensitive, 1);
}
shared_ptr<Selector> Selector::addRecognizer(const shared_ptr<Recognizer> &r){
mElements.push_back(r);
return static_pointer_cast<Selector> (shared_from_this());
......@@ -200,6 +236,14 @@ size_t Selector::_feed(const shared_ptr<ParserContextBase> &ctx, const string &i
return bestmatch;
}
void Selector::_serialize(std::ofstream &fstr){
fstr.write((char*)&mIsExclusive, 1);
writeInt(fstr, (int)mElements.size());
for(auto it = mElements.begin(); it != mElements.end(); ++it){
(*it)->serialize(fstr);
}
}
void Selector::_optimize(int recursionLevel){
for (auto it=mElements.begin(); it!=mElements.end(); ++it){
(*it)->optimize(recursionLevel);
......@@ -265,6 +309,12 @@ void Sequence::_optimize(int recursionLevel){
(*it)->optimize(recursionLevel);
}
void Sequence::_serialize(std::ofstream &fstr){
writeInt(fstr, (int) mElements.size());
for (auto it=mElements.begin(); it!=mElements.end(); ++it){
(*it)->serialize(fstr);
}
}
shared_ptr<Loop> Loop::setRecognizer(const shared_ptr<Recognizer> &element, int min, int max){
mMin=min;
......@@ -293,6 +343,12 @@ bool Loop::_getTransitionMap(TransitionMap* mask){
return mMin!=0; //we must say to upper layer that this loop recognizer is allowed to be optional by returning FALSE
}
void Loop::_serialize(std::ofstream &fstr){
writeInt(fstr, mMin);
writeInt(fstr, mMax);
mRecognizer->serialize(fstr);
}
void Loop::_optimize(int recursionLevel){
mRecognizer->optimize(recursionLevel);
}
......@@ -311,6 +367,14 @@ void CharRange::_optimize(int recursionLevel){
}
void CharRange::_serialize(std::ofstream& fstr){
unsigned char begin, end;
begin = (unsigned char)mBegin;
end = (unsigned char)mEnd;
fstr.write((char*)&begin, 1);
fstr.write((char*)&end, 1);
}
shared_ptr<CharRecognizer> Foundation::charRecognizer(int character, bool caseSensitive){
return make_shared<CharRecognizer>(character, caseSensitive);
......@@ -340,6 +404,11 @@ size_t Literal::_feed(const shared_ptr< ParserContextBase >& ctx, const string&
return mLiteralSize;
}
void Literal::_serialize(ofstream &fstr){
fstr<<mLiteral;
fstr.write("", 1);
}
void Literal::_optimize(int recursionLevel){
}
......@@ -371,6 +440,10 @@ size_t RecognizerPointer::_feed(const shared_ptr<ParserContextBase> &ctx, const
return string::npos;
}
void RecognizerPointer::_serialize(std::ofstream &fstr){
//nothing to do
}
void RecognizerPointer::setPointed(const shared_ptr<Recognizer> &r){
mRecognizer=r;
}
......@@ -489,6 +562,30 @@ int Grammar::getNumRules() const{
return (int)mRules.size();
}
int Grammar::save(const std::string &filename){
ofstream of;
of.open(filename,ofstream::out|ofstream::trunc|ofstream::binary);
if (of.fail()){
BCTBX_SLOGE<<"Could not open "<<filename;
return -1;
}
//serialize the name followed by null character
of<<mName;
of.write("",1);
//iterate over rules
for (auto it = mRules.begin(); it != mRules.end(); ++it){
//serialize the name of the rule
of<<(*it).first;
of.write("",1);
(*it).second->serialize(of);
of.write("",1);
of.write("",1);
}
of.close();
return 0;
}
string tolower(const string &str){
string ret(str);
......
......@@ -26,14 +26,14 @@ else()
set(BELR_LIBRARIES_FOR_TOOLS belr-static)
endif()
foreach(EXECTUABLE belr-parse belr-demo)
set(SOURCE_FILES_CXX ${EXECTUABLE}.cc)
foreach(EXECUTABLE belr-parse belr-demo belr-compiler)
set(SOURCE_FILES_CXX ${EXECUTABLE}.cc)
bc_apply_compile_flags(SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX)
add_executable(${EXECTUABLE} ${SOURCE_FILES_CXX})
set_target_properties(${EXECTUABLE} PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(${EXECTUABLE} ${BELR_LIBRARIES_FOR_TOOLS} ${BCTOOLBOX_CORE_LIBRARIES})
add_executable(${EXECUTABLE} ${SOURCE_FILES_CXX})
set_target_properties(${EXECUTABLE} PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(${EXECUTABLE} ${BELR_LIBRARIES_FOR_TOOLS} ${BCTOOLBOX_CORE_LIBRARIES})
if(APPLE)
set_target_properties(${EXECTUABLE} PROPERTIES LINK_FLAGS "-stdlib=libc++")
set_target_properties(${EXECUTABLE} PROPERTIES LINK_FLAGS "-stdlib=libc++")
endif()
endforeach()
......
/*
* Copyright (C) 2017 Belledonne Communications SARL
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "belr/grammarbuilder.h"
#include "belr/abnf.h"
using namespace std;
using namespace belr;
int main(int argc, char *argv[]){
string file, ofile;
if (argc<3){
cerr<<argv[0]<<" <grammar file to load> <output filename>"<<endl;
return -1;
}
file = argv[1];
ofile = argv[2];
//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.createFromAbnfFile(file, make_shared<CoreRules>());
if (!grammar){
cerr<<"Fail to create grammar."<<endl;
return -1;
}
if (grammar->save(ofile) != 0){
return -1;
}
return 0;
}
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