使用antlr解析|分开的文件

时间:2010-01-26 22:39:32

标签: antlr

所以我认为这应该很简单,但我很难接受它。我正在尝试解析一个|分隔文件,以及任何不以|开头的行是评论。我想我不明白评论是如何运作的。它总是在评论行上出错。这是一个遗留文件,所以没有改变它。这是我的语法。

grammar Route;

@header {
package org.benheath.codegeneration;
}

@lexer::header {
package org.benheath.codegeneration;
}

file: line+;
line: route+ '\n';
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ;
elt: (ELEMENT)*;

COMMENT: ~'|' .* '\n' ;
ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ;
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace

数据:

! a comment
Another comment
| a | abc | b | def | ...

3 个答案:

答案 0 :(得分:1)

这个语法看起来像这样:

parse
  :  line* EOF   
  ;

line
  :  ( comment | values ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values
  :  PIPE ( ELEMENT PIPE )+
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;

要测试它,你只需要在你的语法中加入一些代码:

grammar Route;

@members {
  List<List<String>> values = new ArrayList<List<String>>();
}

parse
  :  line* EOF   
  ;

line
  :  ( comment | v=values {values.add($v.line);} ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values returns [List<String> line]
@init {line = new ArrayList<String>();}
  :  PIPE ( e=ELEMENT {line.add($e.text);} PIPE )*
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;

现在通过调用:

生成词法分析器/解析器
java -cp antlr-3.2.jar org.antlr.Tool Route.g

创建一个类RouteTest.java

import org.antlr.runtime.*;
import java.util.List;

public class RouteTest {
  public static void main(String[] args) throws Exception {
    String data = 
        "a comment\n"+
        "| xxxxx | y |     zzz   |\n"+
        "another comment\n"+
        "| a | abc | b | def |";
    ANTLRStringStream in = new ANTLRStringStream(data);
    RouteLexer lexer = new RouteLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    RouteParser parser = new RouteParser(tokens);
    parser.parse();
    for(List<String> line : parser.values) {
      System.out.println(line);
    }
  }
}

编译所有源文件:

javac -cp antlr-3.2.jar *.java

并运行课程RouteTest

// Windows
java -cp .;antlr-3.2.jar RouteTest

// *nix/MacOS
java -cp .:antlr-3.2.jar RouteTest

如果一切顺利,你会看到打印到你的控制台:

[xxxxx, y, zzz]
[a, abc, b, def]

编辑:请注意,我只是通过允许使用小写字母来简化它,您可以随时扩展该套装。

答案 1 :(得分:0)

将ANTLR用于这样的工作是一个不错的主意,尽管我认为这样做太过分了。例如,(伪代码)很容易:

for each line in file:
if line begins with '|':
    fields = /|\s*([a-z]+)\s*/g

编辑:嗯,你不能表达评论和行 lexically 之间的区别,因为没有任何词汇可以区分它们。提示让你朝着一个可行的方向前进。

line: comment | fields;
comment: NONBAR+ (BAR|NONBAR+) '\n';
fields = (BAR NONBAR)+;

答案 2 :(得分:0)

这似乎有效,我发誓我试过了。将注释更改为小写将其切换为解析器与词法分析器,我仍然没有得到它。

grammar Route;

@header {
    package org.benheath.codegeneration;
}

@lexer::header {
    package org.benheath.codegeneration;
}

file: (line|comment)+;
line: route+ '\n';
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ;
elt: (ELEMENT)*;

comment : ~'|' .* '\n';

ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ;
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace