根据上下文选择性地跳过换行符

时间:2011-12-23 15:52:27

标签: antlr

我必须解析由两部分组成的文件。在第一个中,必须跳过新行。在第二个中,它们很重要并用作分隔符。

我想避免像http://www.antlr.org/wiki/pages/viewpage.action?pageId=1734这样的解决方案,而是使用谓词。

目前,我有类似的东西:

WS:     ( ' ' | '\t' | NEWLINE) {SKIP();};
fragment NEWLINE : '\r'|'\n'|'\r\n';

我尝试添加一个动态范围的变量keepNewline,当“输入”文件的第二部分时,该变量设置为true。

但是,我无法创建正确的谓词来关闭换行符的“跳过”。

非常感谢任何帮助。

最好的问候。

1 个答案:

答案 0 :(得分:4)

这比你想象的要容易:你甚至不需要谓词。

假设您希望仅在<pre> ... </pre>标记内保留换行符。以下虚拟语法就是这样:

grammar Pre;

@lexer::members {
  private boolean keepNewLine = false;
}

parse
 : (t=. 
    {
     System.out.printf("\%-10s '\%s'\n", tokenNames[$t.type], $t.text.replace("\n", "\\n"));
    }
   )* 
   EOF
 ;

Word
 : ('a'..'z' | 'A'..'Z')+
 ;

OPr
 : '<pre>' {keepNewLine = true;}
 ;

CPr
 : '</pre>' {keepNewLine = false;}
 ;

NewLine
 : ('\r'? '\n' | '\r') {if(!keepNewLine) skip();}
 ;

Space
 : (' ' | '\t') {skip();}
 ;

您可以使用该课程进行测试:

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    PreLexer lexer = new PreLexer(new ANTLRFileStream("in.txt"));
    PreParser parser = new PreParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

如果in.txt包含:

foo  bar
<pre>
a

b
</pre>


baz

运行Main类的输出将是:

Word       'foo'
Word       'bar'
OPr        '<pre>'
NewLine    '\n'
Word       'a'
NewLine    '\n'
NewLine    '\n'
Word       'b'
NewLine    '\n'
CPr        '</pre>'
Word       'baz'