我一直在努力尝试(逐步)修改文档中的示例代码,但没有太大的不同,我没有得到我期望的行为。具体来说,“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_;
首先添加 identifier 标记,它也将完美匹配“if”(以及任何其他关键字)。如果你把它改成
this->self += if_ | else_ | identifier | number;
一切都开始正常工作。
这不是 Spirit.Lex 特有的。任何分词器都遵循定义分词的顺序来确定匹配的优先级。
关于c++ - Boost Spirit 和 Lex 解析器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2760812/
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我正在使用ruby1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www