使用antlr解析|分隔的文件
所以我认为这应该很容易,但我现在很难接受。我试图解析一个|分隔的文件,任何不以|开头的行都是注释。我想我不明白评论是怎么起作用的。它总是在注释行中出错。这是一个遗留文件,因此无法更改它。这是我的语法使用antlr解析|分隔的文件,antlr,Antlr,所以我认为这应该很容易,但我现在很难接受。我试图解析一个|分隔的文件,任何不以|开头的行都是注释。我想我不明白评论是怎么起作用的。它总是在注释行中出错。这是一个遗留文件,因此无法更改它。这是我的语法 grammar Route; @header { package org.benheath.codegeneration; } @lexer::header { package org.benheath.codegeneration; } file: line+; line: route+ '
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
数据:
在这样的工作中使用ANTLR是一个好主意,尽管我确实认为这有点过头了。例如,很容易(在伪代码中): 编辑:你不能用词汇来表达注释和行之间的区别,因为没有词汇来区分它们。一个让你朝着一个可行方向前进的提示
line: comment | fields;
comment: NONBAR+ (BAR|NONBAR+) '\n';
fields = (BAR NONBAR)+;
在这样的工作中使用ANTLR是一个好主意,尽管我确实认为这有点过头了。例如,很容易(在伪代码中): 编辑:你不能用词汇来表达注释和行之间的区别,因为没有词汇来区分它们。一个让你朝着一个可行方向前进的提示
line: comment | fields;
comment: NONBAR+ (BAR|NONBAR+) '\n';
fields = (BAR NONBAR)+;
这似乎管用,我发誓我试过了。将注释改为小写将其切换到解析器vs lexer,我仍然不明白
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
这似乎管用,我发誓我试过了。将注释改为小写将其切换到解析器vs lexer,我仍然不明白
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
其语法如下所示:
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;}
;
为了测试它,您只需要在语法中添加一些代码,如下所示:
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;}
;
创建一个类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);
}
}
}
并运行类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]
编辑:请注意,我只允许小写字母,因此简化了一点。当然,您可以随时扩展该集合。该集合的语法如下所示:
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;}
;
为了测试它,您只需要在语法中添加一些代码,如下所示:
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;}
;
创建一个类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);
}
}
}
并运行类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]
编辑:请注意,我只允许小写字母,因此简化了一点。当然,您可以随时扩展集合。欢迎使用SO!小提示:您应该将代码缩进4个空格,这将导致此站点解析并显示为代码,这可以通过突出显示块并按下顶部的“代码”按钮或按Ctrl+K来完成。谢谢,这是我第一篇关于堆栈溢出的帖子,感谢大家的热烈欢迎。欢迎来到SO!小提示:您应该将代码缩进4个空格,这将导致此站点解析并显示为代码,这可以通过突出显示块并按下顶部的“代码”按钮或按Ctrl+K来完成。谢谢,这是我第一次发布堆栈溢出,感谢您的热情欢迎。我同意,但是我试着选择一件简单的事情来开始使用antlr。我同意,但我试着选择一件简单的事情来开始使用antlr。见我的答案。这是词法分析(将文本转换为标记)和解析(理解标记)之间的区别。参见我的答案。这是词法分析(将文本转换为标记)和解析(理解标记)之间的区别。