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