我正在为Fortran 77的一小部分基于Boost Spirit 2.0的解析器工作。我遇到的问题是Fortran 77是面向列的,我一直无法在Spirit中找到任何内容可以允许其解析器具有列感知功能。有没有办法做到这一点?
我真的不需要支持完整的神秘Fortran语法,但它确实需要能够忽略第一列中具有字符的行(Fortran注释),并识别第六列中带有字符的行作为延续线。
似乎处理批处理文件的人至少会遇到与我相同的第一列问题。 Spirit似乎有一个行尾解析器,但不是行首解析器(并且通常不是列(x)解析器)。
答案 0 :(得分:4)
好吧,既然我现在有了答案,我想我应该分享一下。
Fortran 77就像所有其他关心列的语言一样,是一种面向行的语言。这意味着你的解析器必须跟踪EOL,并在解析时实际使用它。
另一个重要的事实是,就我而言,我并不关心解析Fortran可以放在那些早期控制列中的行号。我所需要的只是知道它什么时候告诉我以不同的方式扫描其余部分。
鉴于这两件事,我可以使用Spirit跳过解析器完全处理这个问题。我写了我的
以下是代码:
skip =
// Full line comment
(spirit::eol >> spirit::ascii::alpha >> *(spirit::ascii::char_ - spirit::eol))
[boost::bind (&fortran::parse_info::skipping_line, &pi)]
|
// remaining line comment
(spirit::ascii::char_ ('!') >> *(spirit::ascii::char_ - spirit::eol)
[boost::bind (&fortran::parse_info::skipping_line_comment, &pi)])
|
// Continuation
(spirit::eol >> spirit::ascii::blank >>
spirit::qi::repeat(4)[spirit::ascii::char_ - spirit::eol] >> ".")
[boost::bind (&fortran::parse_info::skipping_continue, &pi)]
|
// empty line
(spirit::eol >>
-(spirit::ascii::blank >> spirit::qi::repeat(0, 4)[spirit::ascii::char_ - spirit::eol] >>
*(spirit::ascii::blank) ) >>
&(spirit::eol | spirit::eoi))
[boost::bind (&fortran::parse_info::skipping_empty, &pi)]
|
// whitespace (this needs to be the last alternative).
(spirit::ascii::space - spirit::eol)
[boost::bind (&fortran::parse_info::skipping_space, &pi)]
;
我建议不要盲目地将它自己用于面向行的Fortran,因为我忽略行号,不同的编译器对有效的注释和连续字符有不同的规则。