Skip to content

iobee/chrysanthemum

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

96 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chrysanthemum (中文名“菊花”)是一个由C++写成的小巧灵活、高度可伸缩、模块化的词法/语法分析框架。
chrysanthemum 是一个纯模板库,包含头文件即可使用,且无任何第三方依赖。chrysanthemum 很大程度上受到 Joel de Guzman
所编写的boost.spirit库的启发。

chrysanthemum 能够极大的简化语法分析器的编写工作,使用户可以在C++环境中“书写”BNF范式从而
快速的构造出对应的词法/文法分析器。使用chrysanthemum可以在100多行代码以内完成一个JSON的解析器(参见unit_test/test_json.cc)。

chrysanthemum 完全以C++0X新标准写成,因此只能用于对C++0X支持比较好的编译器中,MSVC系列因没有提供可变模板参数的支持,
无法使用。目前仅在GCC4.5和GCC4.6环境下测试过,WINDOWS环境可以选择使用MINGW                             

注意:编译时请加上 -std=c++0x 参数以打开C++0X支持.
如果您有好的建议或问题请发送至[email protected]

以下是一个JSON解析器的主体部分:
struct json_grammar
{
    typedef std::string::iterator IT;    
    typedef scanner<IT,line_counter_scanner_policy> scanner_t;
    rule<scanner_t,json_obj,_space> obj;
    rule<scanner_t,json_member,_space> member;
    rule<scanner_t,json_string,_space> string;
    rule<scanner_t,json_value,_space> value;
    rule<scanner_t,json_array,_space> array;
    rule<scanner_t,json_real,_space> real;
    ////////////helpers///////////////
    rule<scanner_t,no_context,no_skip> integer;
    rule<scanner_t,char,no_skip> character;

    json_grammar()
    {


        obj %=    '{' 
                &   ( member <= [=](IT first,IT last) { obj.cur_ctx().map_.insert(member.pop_ctx());return true;} ) % ','
                & '}';
        ////////////////////////////////////
        member %=   string <= [=](IT first,IT last) { member.cur_ctx().first = string.pop_ctx(); return true;}
                  & ':' 
                  & value <= [=](IT first,IT last) { member.cur_ctx().second = value.pop_ctx(); return true;};
        /////////////////////////////////////
        string %=  '"' 
                  & +(character  <= [=](IT first,IT last){ string.cur_ctx() += character.pop_ctx(); return true; })
                & '"';
        ///////////////////////////////////////
        value %=  string <= [=](IT first,IT last){ value.cur_ctx().set<json_string>(string.pop_ctx()); return true;}
                | real <= [=](IT first,IT last) { value.cur_ctx().set<json_real>(real.pop_ctx()); return true; }
                | obj <= [=](IT first,IT last) { value.cur_ctx().set<json_obj>(obj.pop_ctx()); return true; }
                | array <= [=](IT first,IT last) { value.cur_ctx().set<json_array>(array.pop_ctx()); return true; }
                | "true" <= [=](IT first,IT last) { value.cur_ctx().set<json_boolean>(true); return true;  }
                | "false" <= [=](IT first,IT last) { value.cur_ctx().set<json_boolean>(false);  return true; }                
                | "null" <= [=](IT first,IT last) { value.cur_ctx().set<json_null>(json_null()); return true; };
        /////////////////////////////////////////
        array %= '[' 
                & (value <= [=](IT first,IT last) { array.cur_ctx().array_.push_back(value.pop_ctx()); return true; }) % ','
                & ']';
        ////////////////////////////////////////////
        real %= (  integer & -( '.'  & +_digit() & -( ( _literal('e') | 'E' )  & integer ) ) ) 
                            <= [=](IT first,IT last)  { real.cur_ctx() = converter<double>::do_convert(first,last); return true; };
        ////////////////////////////////////////////
        integer %=  -(_literal('+') | '-') & +_digit() ;
        ///////////////////////////////////////////////////////////////////////
        character %=  (_any() - _cntrl() - '"' - '\\') <= [=](IT first,IT last) { character.cur_ctx() = *first; return true; }
                    | "\\\"" <= [=](IT first,IT last) {character.cur_ctx() = '"';return true;}
                    | "\\\\" <= [=](IT first,IT last) {character.cur_ctx() = '\\';return true;}
                    | "\\/" <= [=](IT first,IT last) {character.cur_ctx() = '/';return true;}
                    | "\\b" <= [=](IT first,IT last) {character.cur_ctx() = '\b';return true;}
                    | "\\f" <= [=](IT first,IT last) {character.cur_ctx() = '\f';return true;}
                    | "\\n" <= [=](IT first,IT last) {character.cur_ctx() = '\n';return true;}
                    | "\\r" <= [=](IT first,IT last) {character.cur_ctx() = '\r';return true;}
                    | "\\t" <= [=](IT first,IT last) {character.cur_ctx() = '\t';return true;}
                    | ( "\\u" & (_digit()&_digit())  
                                <= [=](IT first,IT last) { int i = *first++ - '0'; i = i*10 + (*first-'0'); character.cur_ctx() = (char)i; return true;}
                      );
    }

    
};





Releases

No releases published

Packages

No packages published