如何用位置信息注释AST
How to annotate the AST with position information?
我使用Boost Spirit在一个小的编译器项目中解析源文件。
如果在解析过程中出现错误,我可以打印错误的位置,但在稍后的阶段,通常是在执行语义检查时,我该怎么做?
我的源文件使用自动规则解析为抽象语法树。我想将行和列信息添加到AST节点中。有没有一种简单的方法可以在解析过程中实现这一点?
我在Lexer中使用boost::spirit::classic::position_iterator2,然后在语法中使用这个Lexer。
谢谢
编辑:
lexer的定义如下:
typedef std::string::iterator base_iterator_type;
typedef boost::spirit::classic::position_iterator2<base_iterator_type> pos_iterator_type;
typedef boost::spirit::lex::lexertl::token<pos_iterator_type> Tok;
typedef boost::spirit::lex::lexertl::actor_lexer<Tok> lexer_type;
template<typename L>
class SpiritLexer : public lex::lexer<L> {
//Token definitions
}
typedef lexer_type::iterator_type Iterator;
typedef SpiritLexer<lexer_type> Lexer;
语法是这样定义的:
struct EddiGrammar : qi::grammar<lexer::Iterator, ast::SourceFile()> {
EddiGrammar(const lexer::Lexer& lexer);
//Token definitions
};
最后,以下是我如何解析来源:
ast::SourceFile program
std::ifstream in(file.c_str());
in.unsetf(std::ios::skipws);
in.seekg(0, std::istream::end);
std::size_t size(static_cast<size_t>(in.tellg()));
in.seekg(0, std::istream::beg);
std::string contents(size, 0);
in.read(&contents[0], size);
pos_iterator_type position_begin(contents.begin(), contents.end(), file);
pos_iterator_type position_end;
Lexer lexer;
EddiGrammar grammar(lexer);
bool r = spirit::lex::tokenize_and_parse(position_begin, position_end, lexer, grammar, program);
在我的语法中,我通过引用一些lexer标记来使用lexer。例如:
else_ %=
lexer.else_
>> lexer.left_brace
>> *(instruction)
>> lexer.right_brace;
我的所有AST节点都是使用自动规则构建的。
我找到了解决这个问题的方法。
我编写了一个简单的终端解析器,只需获取当前位置并将其添加到AST节点。
这是我写的解析器:
namespace boost { namespace spirit {
BOOST_SPIRIT_TERMINAL(position)
template <>
struct use_terminal<qi::domain, tag::position> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
struct position : primitive_parser<position>
{
position(const eddic::lexer::pos_iterator_type& position_begin) : position_begin(position_begin) {}
template <typename Context, typename Iterator>
struct attribute {
typedef eddic::ast::Position type;
};
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& /*context*/, Skipper const& skipper, Attribute& attr) const
{
qi::skip_over(first, last, skipper);
auto& pos = position_begin.get_position();
attr.theLine = position_begin.get_currentline();
attr.file = pos.file;
attr.column = pos.column;
attr.line = pos.line;
return true;
}
template <typename Context>
info what(Context& context) const {
return info("position");
}
const eddic::lexer::pos_iterator_type& position_begin;
};
template <typename Modifiers>
struct make_primitive<tag::position, Modifiers> {
typedef position result_type;
result_type operator()(unused_type, eddic::lexer::Lexer const& lexer, unused_type) const
{
return result_type(lexer);
}
};
}}}
以及我用来存储信息的结构:
struct Position {
std::string file;
std::string theLine;
int line;
int column;
};
它工作得很好,但我必须将位置迭代器传递给解析器。如果有人知道从提供给解析函数的迭代器中获取position_iteror2迭代器的方法,我将不胜感激。
相关文章:
- Visual Studio 2019:插入多个C++风格的单行注释
- 如何克服提升精神AST混乱
- clang 插件:在编译过程中修改 AST
- Boost.Spirit将表达转换为AST
- 类继承,ENUM 与 AST 类实现的问题
- VSCode 中带有 C/C++ 扩展名的多行注释缩进错误
- 如果我注释掉换行符,为什么'string'会成为一个不合格的变量
- 为什么 ## aka 令牌粘贴运算符不适用于 C 和 C++ 中的注释?
- Windows Clang Ast Dump
- 在 // C++注释中使用 \\ 是否合法?(C++评论中的LaTeX方程)
- 如何将 AST 用于自定义前端操作和 clang 静态分析
- 注释一行使代码工作,而没有它,代码不起作用
- 使用 Doxygen 在不同文件中注释函数
- 如何设置叮当格式的注释编译指示,以免触及多行doxygen注释?
- 与不同变量类型相比,用于变量的 Clang AST 匹配器
- Qt - 带有注释的 JSON
- 如何检测 Clang AST C++中的静态函数
- 如何在 boost::spirit::qi 中将某些语义操作排除在 AST 之外
- Visual Studio Community 代码分析的质量与 SAL 注释
- 如何用位置信息注释AST