2010-01-26 77 views
1

所以我认为这应该很容易,但我有一个艰难的时间。我试图解析一个|分隔文件以及任何不以|开头的行是一条评论。我想我不明白评论如何工作。它总是在注释行上出错。这是一个传统文件,所以没有改变它。这是我的语法。使用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 | ... 
+0

欢迎来到SO!小提示:您应该用4个空格缩进代码,这会导致该站点解析并显示为代码,这可以通过突出显示块并按顶部的“代码”按钮或点击Ctrl + K来完成。 – RCIX 2010-01-26 22:49:35

+0

谢谢,这是我第一次发布Stack Overflow,感谢热烈的欢迎。 – Ben 2010-01-26 23:06:19

回答

0

这是一个不错的主意,使用ANTLR进行这样的工作,但我不认为这是矫枉过正。例如,这将是很容易的(伪代码):

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

编辑:嗯,你无法表达意见和线词法之间的区别,因为没有什么词汇区分它们。提示让你朝着一个可行的方向发展。

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

好吧,我同意,但我试图选择一个容易的事情与antlr做开始。 – Ben 2010-01-26 23:04:48

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 
+0

看到我的答案。 * lexing *(将文本转换为令牌)和* parsing *(理解令牌)之间的区别。 – 2010-01-27 01:58:25

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] 

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