代码之家  ›  专栏  ›  技术社区  ›  T.E.D.

Boost::Spirit中的字符列分析

  •  4
  • T.E.D.  · 技术社区  · 15 年前

    我正在研究 Boost Spirit 基于2.0的Fortran 77的一个子集分析器。我遇到的问题是fortran 77是面向列的,我在精神上找不到任何东西可以让它的解析器感知列。有什么办法吗?

    我不需要支持完整的奥术Fortran语法,但是它需要能够忽略第一列中有字符的行(Fortran注释),并将第六列中有字符的行识别为连续行。

    似乎处理批处理文件的人至少会遇到与我相同的第一列问题。spirit似乎有一个行尾分析器,但不是行首分析器(当然不是列(x)分析器)。

    1 回复  |  直到 9 年前
        1
  •  4
  •   wilx    9 年前

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

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