标签: boost-spirit-lex

如何对Boost Spirit Parser进行基准测试?

我正在研究编译器,我想提高它的性能.我发现大约50%的时间花在解析源文件上.由于源文件非常小,之后我做了很多转换,在我看来它是可以完善的.

我的解析器是一个带有词法分析器(带有lexer :: pos_iterator)的Boost Spirit解析器,我有一个中等大小的语法.我正在将源解析为AST.

我的问题是我不知道解析过程中花费的时间最多:AST节点,词法分析器,解析器规则或内存的副本.

我不认为这是I/O问题,因为我正在使用SSD并且我在开始时完全读取文件然后仅使用内存版本.

我尝试使用分析器,但是花费时间的方法是Boost的一些方法,其名称长达数百个字符,我不知道它们到底做了什么......

那么,是否有一种首选方法来对Boost Spirit Parser及其语法进行基准测试?或者是否有一些规则可用于验证某些特定点的效率?

谢谢

感兴趣的人的来源:

c++ benchmarking boost-spirit boost-spirit-qi boost-spirit-lex

15
推荐指数
1
解决办法
1678
查看次数

我无法获取令牌的字符串值

我尝试使用Boost Spirit为一个小编程语言实现一个Lexer.

我必须得到一个令牌的值,我得到一个bad_get异常:

在抛出'boost :: bad_get'的实例后调用终止
what():boost :: bad_get:失败的值得到使用boost :: get Aborted

这样做时我得到了这个例外:

std::string contents = "void";

base_iterator_type first = contents.begin();
base_iterator_type last = contents.end();

SimpleLexer<lexer_type> lexer;

iter = lexer.begin(first, last);
end = lexer.end();

std::cout << "Value = " << boost::get<std::string>(iter->value()) << std::endl;
Run Code Online (Sandbox Code Playgroud)

我的词法分析器定义如下:

typedef std::string::iterator base_iterator_type;
typedef boost::spirit::lex::lexertl::token<base_iterator_type, boost::mpl::vector<unsigned int, std::string>> Tok;
typedef lex::lexertl::actor_lexer<Tok> lexer_type;

template<typename L>
class SimpleLexer : public lex::lexer<L> {
    private:

    public:
        SimpleLexer() {
            keyword_for = "for";
            keyword_while = "while";
            keyword_if = "if";
            keyword_else = "else"; …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-lex

10
推荐指数
1
解决办法
1687
查看次数

如何使用boost :: spirit :: lex实现include指令?

我有一个简单的配置文件解析器,由spirit :: lex和spirit :: qi构建.当词法分析器到达模式时,include "path"我希望包含文件的文本.您可能知道,spirit :: lexer :: begin()启动扫描过程:

// Read file contents into a std::string
...

// _first and _last are const char*
_first = _contents.c_str();
_last  = &_first[_input.size()];

// _token is a lexer::iterator_type for the current token
_token = _lexer.begin(_first, _last);
Run Code Online (Sandbox Code Playgroud)

我的想法是有一个存储lexer状态的堆栈表示为结构:

struct LexerState
{
    const char* first;
    const char* last;
    std::string contents;
};
Run Code Online (Sandbox Code Playgroud)

词法分析器将识别模式,include "path"并在语义动作中提取包含文件的路径.然后,将当前词法分析器状态推入堆栈,将文件的内容加载到字符串中,并使用lexer :: begin()按上述方式初始化新状态.

当词法分析器找到EOF字符时,弹出堆栈并使用先前的词法分析器状态变量调用lexer :: begin().

可以这样重复调用lexer :: begin()吗?如何让lex :: lexer识别include "path"模式和EOF字符而不将令牌返回到qi解析器?

最后,有没有其他或更好的方法来实现这一目标?

c++ boost boost-spirit boost-spirit-lex

6
推荐指数
1
解决办法
505
查看次数

为什么这个boost :: spirit :: qi规则与输入不匹配?

我尝试继续处理我之前的示例并扩展规则.我的问题是,使用ID_IDENTIFIER的规则不起作用 - 虽然我知道词法分析器正在工作(使用单元测试).

这是一个例子:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>

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

enum LexerIDs { ID_IDENTIFIER, ID_WHITESPACE, ID_INTEGER, ID_FLOAT, ID_PUNCTUATOR };

template <typename Lexer>
struct custom_lexer : lex::lexer<Lexer>
{
    custom_lexer()
        : identifier    ("[a-zA-Z_][a-zA-Z0-9_]*")
        , white_space   ("[ \\t\\n]+")
        , integer_value ("[1-9][0-9]*")
        , hex_value     ("0[xX][0-9a-fA-F]+")
        , float_value   ("[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?")
        , float_value2  ("[0-9]+\\.([eE][+-]?[0-9]+)?")
        , punctuator    ("\\[|\\]|\\(|\\)|\\.|&>|\\*\\*|\\*|\\+|-|~|!|\\/|%|<<|>>|<|>|<=|>=|==|!=|\\^|&|\\||\\^\\^|&&|\\|\\||\\?|:|,")// [ ] ( ) . &> ** * + - ~ ! / % << >> < > <= >= == != ^ & …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-qi boost-spirit-lex

6
推荐指数
1
解决办法
216
查看次数

使用boost :: spirit :: lex和whitespace来解决问题

我尝试学习使用boost :: spirit.为此,我想创建一些简单的词法分析器,将它们组合起来,然后使用精神开始解析.我尝试修改示例,但它没有按预期运行(结果r不正确).

这是词法分析器:

#include <boost/spirit/include/lex_lexertl.hpp>

namespace lex = boost::spirit::lex;

template <typename Lexer>
struct lexer_identifier : lex::lexer<Lexer>
{
    lexer_identifier()
        : identifier("[a-zA-Z_][a-zA-Z0-9_]*")
        , white_space("[ \\t\\n]+")
    {
        using boost::spirit::lex::_start;
        using boost::spirit::lex::_end;

        this->self = identifier;
        this->self("WS") = white_space;
    }
    lex::token_def<> identifier;
    lex::token_def<> white_space;
    std::string identifier_name;
};
Run Code Online (Sandbox Code Playgroud)

这是我正在尝试运行的示例:

#include "stdafx.h"

#include <boost/spirit/include/lex_lexertl.hpp>
#include "my_Lexer.h"

namespace lex = boost::spirit::lex;

int _tmain(int argc, _TCHAR* argv[])
{
    typedef lex::lexertl::token<char const*,lex::omit, boost::mpl::false_> token_type;
    typedef lex::lexertl::lexer<token_type> lexer_type;

    typedef lexer_identifier<lexer_type>::iterator_type iterator_type;

    lexer_identifier<lexer_type> my_lexer;

    std::string test("adedvied das934adf dfklj_03245");

    char const* first …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-lex

5
推荐指数
1
解决办法
1151
查看次数

如何在boost :: spirit :: lex基lexer中添加符号表接口?

要实现对typedef的支持,当lexer识别标识符并返回不同的标记时,您需要查找符号表.这在flex lexer中很容易完成.我试图使用boost Spirit来构建解析器并在示例中查看,但它们都没有在词法分析器和解析器之间传递任何上下文信息.在mini c编译器教程示例中,最简单的方法是什么?

boost boost-spirit boost-spirit-lex

4
推荐指数
1
解决办法
490
查看次数

如何将boost :: spirit :: lex标记的值从iterator_range转换为字符串?

当我尝试从iterator_range转换令牌的值时,词法分析器在尝试读取下一个令牌时失败.

这是包含令牌定义的Tokens结构:(我不认为这是相关的,但我包括以防万一.)

template <typename Lexer>
struct Tokens : boost::spirit::lex::lexer<Lexer>
{
    Tokens();

    boost::spirit::lex::token_def<std::string> identifier;
    boost::spirit::lex::token_def<std::string> string;
    boost::spirit::lex::token_def<bool> boolean;
    boost::spirit::lex::token_def<double> real;
    boost::spirit::lex::token_def<> comment;
    boost::spirit::lex::token_def<> whitespace;
};

template <typename Lexer>
Tokens<Lexer>::Tokens()
{
    // Define regex macros
    this->self.add_pattern
        ("LETTER", "[a-zA-Z_]")
        ("DIGIT", "[0-9]")
        ("INTEGER", "-?{DIGIT}+")
        ("FLOAT", "-?{DIGIT}*\\.{DIGIT}+");

    // Define the tokens' regular expressions
    identifier = "{LETTER}({LETTER}|{DIGIT})*";
    string = "\"[a-zA-Z_0-9]*\"";
    boolean = "true|false";
    real = "{INTEGER}|{FLOAT}";
    comment = "#[^\n\r\f\v]*$";
    whitespace = "\x20\n\r\f\v\t+";

    // Define tokens
    this->self
        = identifier
        | string
        | boolean
        | real
        | '{' …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-lex

4
推荐指数
1
解决办法
1483
查看次数

尽管令牌不完整,但提升精神意味着成功解析

我有一个非常简单的路径构造,我试图用boost spirit.lex解析.

我们有以下语法:

token := [a-z]+
path := (token : path) | (token)
Run Code Online (Sandbox Code Playgroud)

所以我们这里只讨论冒号分隔的小写ASCII字符串.

我有三个例子"xyz","abc:xyz","abc:xyz:".

前两个应被视为有效.第三个,有一个尾随结肠,不应被视为有效.不幸的是,解析器我已经认识到这三个都是有效的.语法不应该允许空令牌,但显然精神就是这样做的.为了让第三个被拒绝,我错过了什么?

此外,如果您阅读下面的代码,则在注释中还有另一个版本的解析器要求所有路径以分号结尾.当我激活那些线时,我可以得到适当的行为(即拒绝"abc:xyz:;"),但这不是我想要的.

有人有主意吗?

谢谢.

#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 <iostream>
#include <string>

using namespace boost::spirit;
using boost::phoenix::val;

template<typename Lexer>
struct PathTokens : boost::spirit::lex::lexer<Lexer>
{
      PathTokens()
      {
         identifier = "[a-z]+";
         separator = ":";

         this->self.add
            (identifier)
            (separator)
            (';')
            ;
      }
      boost::spirit::lex::token_def<std::string> identifier, separator;
};


template <typename Iterator>
struct PathGrammar 
   : boost::spirit::qi::grammar<Iterator> 
{
      template <typename TokenDef>
      PathGrammar(TokenDef const& tok)
         : PathGrammar::base_type(path)
      {
         using boost::spirit::_val; …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-lex

4
推荐指数
1
解决办法
904
查看次数

有没有办法将spirit :: lex字符串标记的内容与spirit :: qi语法中的文字进行匹配

我正在编写DSL并使用Boost Spirit词法分析器来标记我的输入.在我的语法中,我想要一个类似于此的规则(tok词法分析器在哪里):

header_block =
    tok.name >> ':' >> tok.stringval > ';' >>
    tok.description >> ':' >> tok.stringval > ';'
  ;
Run Code Online (Sandbox Code Playgroud)

而不是为语言指定保留字(例如"name","description")并处理词法分析器和语法之间的同步,我想只是将匹配的所有内容标记[a-zA-Z_]\w*为单个标记类型(例如tok.symbol),并让语法梳理出来.如果我没有使用词法分析器,我可能会这样做:

stringval = lexeme['"' >> *(char_ - '"') >> '"'];
header_block =
    lit("name") >> ':' >> stringval > ';' >>
    lit("description") >> ':' >> stringval > ';'
  ;
Run Code Online (Sandbox Code Playgroud)

使用词法分析器,我可以编译以下规则,但当然它匹配的比我想要的多 - 它不关心特定的符号值"name"和"description":

header_block =
    tok.symbol >> ':' >> tok.stringval > ';' >>
    tok.symbol >> ':' >> tok.stringval > ';'
  ;
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是这样的:

header_block = …
Run Code Online (Sandbox Code Playgroud)

c++ dsl boost-spirit boost-spirit-qi boost-spirit-lex

3
推荐指数
1
解决办法
529
查看次数

boost :: spirit :: lex,如何生成文件令牌的结尾?

问题很简单,我写了一个词法分析器,使用boost :: spirit,但是我似乎找不到方法来生成EOF令牌. - 那怎么会这样做呢?

token boost-spirit eof boost-spirit-lex

3
推荐指数
1
解决办法
247
查看次数