在Boost :: Spirit中解析字符列

时间:2009-09-22 21:34:01

标签: parsing boost-spirit

我正在为Fortran 77的一小部分基于Boost Spirit 2.0的解析器工作。我遇到的问题是Fortran 77是面向列的,我一直无法在Spirit中找到任何内容可以允许其解析器具有列感知功能。有没有办法做到这一点?

我真的不需要支持完整的神秘Fortran语法,但它确实需要能够忽略第一列中具有字符的行(Fortran注释),并识别第六列中带有字符的行作为延续线。

似乎处理批处理文件的人至少会遇到与我相同的第一列问题。 Spirit似乎有一个行尾解析器,但不是行首解析器(并且通常不是列(x)解析器)。

1 个答案:

答案 0 :(得分:4)

好吧,既然我现在有了答案,我想我应该分享一下。

Fortran 77就像所有其他关心列的语言一样,是一种面向行的语言。这意味着你的解析器必须跟踪EOL,并在解析时实际使用它。

另一个重要的事实是,就我而言,我并不关心解析Fortran可以放在那些早期控制列中的行号。我所需要的只是知道它什么时候告诉我以不同的方式扫描其余部分。

鉴于这两件事,我可以使用Spirit跳过解析器完全处理这个问题。我写了我的

  • 如果第一个(评论)列包含字母字符,则跳过整行。
  • 如果没有任何内容,请跳过整行。
  • 如果第五列包含'。',则忽略前面的EOL和第五列的所有内容。 (续行)。这使它适用于前一行。
  • 跳过所有非eol空格(在Fortran中甚至空格也无关紧要。是的,这是一种奇怪的语言。)

以下是代码:

        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,因为我忽略行号,不同的编译器对有效的注释和连续字符有不同的规则。