我一直在努力尝试(逐步)修改文档中的示例代码,但没有太大的不同,我没有得到我期望的行为.具体来说,“if”语句在(我的意图是)它应该传递时失败(有一个“else”但是在调试期间删除了部分解析器).赋值语句工作正常.我有一个“while”语句,它与“if”语句有同样的问题,所以我相信如果我能得到帮助来弄清楚为什么一个不工作它应该很容易让另一个去.它必须是一种微妙的,因为这几乎是逐字逐句的,其中一个例子.
#include <iostream>
#include <fstream>
#include <string>

#define BOOST_SPIRIT_DEBUG
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_container.hpp>

namespace qi  = boost::spirit::qi;
namespace lex = boost::spirit::lex;

inline std::string read_from_file( const char* infile )
{
    std::ifstream instream( infile );
    if( !instream.is_open() )
    {
        std::cerr << "Could not open file: \"" << infile << "\"" << std::endl;
        exit( -1 );
    }
    instream.unsetf( std::ios::skipws );
    return( std::string(
                std::istreambuf_iterator< char >( instream.rdbuf() ),std::istreambuf_iterator< char >()
          ) );
}

template< typename Lexer >
struct LangLexer : lex::lexer< Lexer >
{
    LangLexer()
    {
        identifier = "[a-zA-Z][a-zA-Z0-9_]*";
        number = "[-+]?(\\d*\\.)?\\d+([eE][-+]?\\d+)?";

        if_ = "if";
        else_ = "else";

        this->self = lex::token_def<> ( '(' ) | ')' | '{' | '}' | '=' | ';';
        this->self += identifier | number | if_ | else_;

        this->self( "WS" ) = lex::token_def<>( "[ \\t\\n]+" );

    }

    lex::token_def<> if_,else_;
    lex::token_def< std::string > identifier;
    lex::token_def< double > number;
};

template< typename Iterator,typename Lexer >
struct LangGrammar : qi::grammar< Iterator,qi::in_state_skipper< Lexer > >
{
    template< typename TokenDef >
    LangGrammar( const TokenDef& tok ) : LangGrammar::base_type( program )
    {
        using boost::phoenix::val;
        using boost::phoenix::ref;
        using boost::phoenix::size;

        program = +block;
        block = '{' >> *statement >> '}';
        statement = assignment | if_stmt;
        assignment = ( tok.identifier >> '=' >> expression >> ';' );
        if_stmt = ( tok.if_ >> '(' >> expression >> ')' >> block );
        expression = ( tok.identifier[ qi::_val = qi::_1 ] | tok.number[ qi::_val = qi::_1 ] );

        BOOST_SPIRIT_DEBUG_NODE( program );
        BOOST_SPIRIT_DEBUG_NODE( block );
        BOOST_SPIRIT_DEBUG_NODE( statement );
        BOOST_SPIRIT_DEBUG_NODE( assignment );
        BOOST_SPIRIT_DEBUG_NODE( if_stmt );
        BOOST_SPIRIT_DEBUG_NODE( expression );
    }

    qi::rule< Iterator,qi::in_state_skipper< Lexer > > program,block,statement;
    qi::rule< Iterator,qi::in_state_skipper< Lexer > > assignment,if_stmt;

    typedef boost::variant< double,std::string > expression_type;
    qi::rule< Iterator,expression_type(),qi::in_state_skipper< Lexer > > expression;
};

int main( int argc,char** argv )
{
    typedef std::string::iterator base_iterator_type;
    typedef lex::lexertl::token< base_iterator_type,boost::mpl::vector< double,std::string > > token_type;
    typedef lex::lexertl::lexer< token_type > lexer_type;
    typeDef LangLexer< lexer_type > LangLexer;
    typeDef LangLexer::iterator_type iterator_type; 
    typeDef LangGrammar< iterator_type,LangLexer::lexer_def > LangGrammar;

    LangLexer lexer;
    LangGrammar grammar( lexer );

    std::string str( read_from_file( 1 == argc ? "boostLexTest.dat" : argv[1] ) );

    base_iterator_type strBegin = str.begin();
    iterator_type tokenItor = lexer.begin( strBegin,str.end() );
    iterator_type tokenItorEnd = lexer.end(); 

    std::cout << std::setfill( '*' ) << std::setw(20) << '*' << std::endl <<
        str
        << std::endl << std::setfill( '*' ) << std::setw(20) << '*' << std::endl;

    bool result = qi::phrase_parse( tokenItor,tokenItorEnd,grammar,qi::in_state( "WS" )[ lexer.self ] );

    if( result )
    {
        std::cout << "Parsing successful" << std::endl;
    }
    else
    {
        std::cout << "Parsing error" << std::endl;
    }

    return( 0 );
}

这是运行它的输出(读入字符串的文件首先在main中转出)

********************
{
    a = 5;
    if( a ){ b = 2; }
}


********************
<program>
  <try>{</try>
  <block>
    <try>{</try>
    <statement>
      <try></try>
      <assignment>
        <try></try>
<expression>
  <try></try>
  <success>;</success>
  <attributes>(5)</attributes>
</expression>
        <success></success>
        <attributes>()</attributes>
      </assignment>
      <success></success>
      <attributes>()</attributes>
    </statement>
    <statement>
      <try></try>
      <assignment>
        <try></try>
        <fail/>
      </assignment>
      <if_stmt>
        <try>
    if(</try>
        <fail/>
      </if_stmt>
      <fail/>
    </statement>
    <fail/>
  </block>
  <fail/>
</program>
Parsing error

解决方法

问题是您将标记定义添加到词法分析器的顺序.你的代码
this->self += identifier | number | if_ | else_;

首先添加标识符标记,它将与’if'(和任何其他关键字)完全匹配.如果你改变它

this->self += if_ | else_ | identifier | number;

每一件事都应该开始发挥作用.

这对Spirit.Lex来说并不具体.任何标记化器都遵循定义标记的顺序以确定匹配的优先级.

c – 提升精神和Lex解析器问题的更多相关文章

  1. ios – 我可以安全地在@try catch块中包装’CoreData无法解决错误’错误

    )是的,我偶尔会得到’CoreData无法完成故障’的错误.在我的特定应用程序中,这通常发生在一种“数据绑定”过程中,因此我可以安全地丢弃故障对象并继续前进.我想通过在@try-catch块中包装数据绑定的循环内部并且只跳过我得到CoreData错误的行来完成此操作.我可以使用CoreData安全地执行此操作吗?

  2. 你如何压缩iOS上的Realm DB?

    我想定期在iOS上压缩一个Realm实例来恢复空间.我认为该过程是将数据库复制到临时位置,然后将其复制回来并使用新的default.realm文件.我的问题是Realm()就像一个单例并且回收对象,所以我无法真正关闭它并告诉它打开新的default.realm文件.这里的文档(https://realm.io/docs/objc/latest/api/Classes/RLMRealm.html)建

  3. ios – 捕获NSKeyedUnarchiver异常

    在Swift中,如果无法取消存档数据,NSKeyedUnarchiver.unarchiveObjectWithData(data)将抛出异常.在某些情况下,我们无法保证数据是否未损坏,例如从文件读取时.我不知道Swift中的try/catch机制,也不知道像canUnarchive这样有助于防止异常的方法.除了在Obj-C中实现try/catch之外,还有一个纯Swift解决方案来解决这个问题吗

  4. ios – 使用swift进行异常处理

    catch来处理它.如果故事板中没有视图控制器,则无法执行任何操作.这是程序员的错误,创建它的人应该处理这些问题.你不能因为这种错误而责怪iOS运行时.

  5. ios – Swift 3 – 将文件夹从主包复制到文档目录

    我的主要包中包含文件夹,我想在首次启动应用程序时将它们复制/剪切到文档目录,以便从那里访问它们.我见过一些例子,但他们都在Obj-C中,我正在使用Swift3.我怎么能这样做?解决方法我设法使用2个功能:

  6. Swift 2.0 try? 的替代方法

    你可以配合着if-let或者guard语句来使用try?但你可以试着写出try?实际上我也不太喜欢tryit这个名字,你用你喜欢的名字代替就好。你可以以同样的方法调用它:你仍然不能基于错误类型和错误细节来制定错误处理策略,但是这种实现方式也不像try?你也可以修改tryit函数,让它也能接受做错误处理的代码块,但因为要处理两种不同的代码块,这个函数就会变得相当臃肿。如果要用try而且又需要进行错误处理的话,你就必须得用do-catch或者像结果枚举之类的其它方法了。

  7. The Swift Programming Language 翻译 —— 错误处理

    Swift支持抛出、捕获、传递和操作等四种方式来处理程序运行时出现的可恢复性错误。表示错误类型在Swift中,错误类型用继承了ErrorType协议的类型来表示。Swift中处理错误的方式有如下四种:使用throw关键字继续向上传递这个错误、使用do-catch表达式处理这个错误、使用try?下面例子中的buyFavoriteSnack方法调用了vend方法,任何vend方法抛出的错误都将传递给他,他选择继续向上传递这些错误。x和y的类型是someThrowingFunction()的返回值类型对应的可选

  8. Swift 2 jSON Call can throw but it is not marked with try

    NSDictionary第一种用法:第二种用法:letjsonData=tryNSJSONSerialization.JSONObjectWithData(urlData!

  9. Swift2.0提供所try catch异常捕捉

    原代码中,AVAudioPlayer的构造函数有了可抛出错误的重载函数,现在的原型不接受第二个error参数,函数不再为failable,应使用trycatch捕捉异常

  10. Swift 读取本地json文件时的异常捕获(try catch)的使用

    Swift读取本地json文件时的异常捕获(trycatch)的使用

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部