我想将csv文件中的每个条目都更改为“BlahBlah” 为此,我有antlr语法
grammar CSV;
file : hdr row* row1;
hdr : row;
row : field (',' value1=field)* '\r'? '\n'; // '\r' is optional at the end of a row of CSV file ..
row1 : field (',' field)* '\r'? '\n'?;
field
: TEXT
{
$setText("BlahBlah");
}
| STRING
|
;
TEXT : ~[,\n\r"]+ ;
STRING : '"' ('""' | ~'"')* '"' ;
但是当我在antlr4上运行时
error(63): CSV.g4:13:3: unknown attribute reference setText in $setText
make: *** [run] Error 1
为什么antlr4不支持setText,还有其他替换文本吗?
答案 0 :(得分:2)
<强> TL;博士强>:
鉴于以下语法(源自原始CSV.g4样本和OP的语法尝试(参见问题)):
grammar CSVBlindText;
@header {
import java.util.*;
}
/** Derived from rule "file : hdr row+ ;" */
file
locals [int i=0]
: hdr ( rows+=row[$hdr.text.split(",")] {$i++;} )+
{
System.out.println($i+" rows");
for (RowContext r : $rows) {
System.out.println("row token interval: "+r.getSourceInterval());
}
}
;
hdr : row[null] {System.out.println("header: '"+$text.trim()+"'");} ;
/** Derived from rule "row : field (',' field)* '\r'? '\n' ;" */
row[String[] columns] returns [Map<String,String> values]
locals [int col=0]
@init {
$values = new HashMap<String,String>();
}
@after {
if ($values!=null && $values.size()>0) {
System.out.println("values = "+$values);
}
}
// rule row cont'd...
: field
{
if ($columns!=null) {
$values.put($columns[$col++].trim(), $field.text.trim());
}
}
( ',' field
{
if ($columns!=null) {
$values.put($columns[$col++].trim(), $field.text.trim());
}
}
)* '\r'? '\n'
;
field
: TEXT
| STRING
|
;
TEXT : ~[',\n\r"]+ {setText( "BlahBlah" );} ;
STRING : '"' ('""'|~'"')* '"' ; // quote-quote is an escaped quote
一个人:
$> antlr4 -no-listener CSVBlindText.g4
$> grep setText CSVBlindText*java
CSVBlindTextLexer.java: setText( "BlahBlah" );
编译它完美无瑕:
$> javac CSVBlindText*.java
Testdata(刚重命名的users.csv文件):
$> cat blinded_by_grammar.csv
User, Name, Dept
parrt, Terence, 101
tombu, Tom, 020
bke, Kevin, 008
测试中的收益率:
$> grun CSVBlindText file blinded_by_grammar.csv
header: 'BlahBlah,BlahBlah,BlahBlah'
values = {BlahBlah=BlahBlah}
values = {BlahBlah=BlahBlah}
values = {BlahBlah=BlahBlah}
3 rows
row token interval: 6..11
row token interval: 12..17
row token interval: 18..23
所以看起来setText()
应该在生产的分号之前注入,而不是在替代品之间注入(在这里疯狂猜测; - )
以前的迭代:
只是猜测,因为我1)目前没有可用的antlr4和2)现在没有写ANTLR4语法很长一段时间 - 也许没有美元($)?
grammar CSV;
file : hdr row* row1;
hdr : row;
row : field (',' value1=field)* '\r'? '\n'; // '\r' is optional at the end of a row of CSV file ..
row1 : field (',' field)* '\r'? '\n'?;
field
: TEXT
{
setText("BlahBlah");
}
| STRING
|
;
TEXT : ~[,\n\r"]+ ;
STRING : '"' ('""' | ~'"')* '"' ;
更新:现在有一个antlr 4.5.2(至少通过brew
)而不是4.5.3可用,我深入研究并回答了OP下面的一些评论:如果语法定义良好,将在lexer java模块中生成setText()
。不幸的是,像我一样调试antlr4
语法是......但是非常好的语言构建工具包IMO。
示例会话:
$> antlr4 -no-listener CSV.g4
$> grep setText CSVLexer.java
setText( String.valueOf(getText().charAt(1)) );
使用的语法: (通过以下方式检索的示例代码中被攻击:
curl -O http://media.pragprog.com/titles/tpantlr2/code/tpantlr2-code.tgz
)
grammar CSV;
@header {
import java.util.*;
}
/** Derived from rule "file : hdr row+ ;" */
file
locals [int i=0]
: hdr ( rows+=row[$hdr.text.split(",")] {$i++;} )+
{
System.out.println($i+" rows");
for (RowContext r : $rows) {
System.out.println("row token interval: "+r.getSourceInterval());
}
}
;
hdr : row[null] {System.out.println("header: '"+$text.trim()+"'");} ;
/** Derived from rule "row : field (',' field)* '\r'? '\n' ;" */
row[String[] columns] returns [Map<String,String> values]
locals [int col=0]
@init {
$values = new HashMap<String,String>();
}
@after {
if ($values!=null && $values.size()>0) {
System.out.println("values = "+$values);
}
}
// rule row cont'd...
: field
{
if ($columns!=null) {
$values.put($columns[$col++].trim(), $field.text.trim());
}
}
( ',' field
{
if ($columns!=null) {
$values.put($columns[$col++].trim(), $field.text.trim());
}
}
)* '\r'? '\n'
;
field
: TEXT
| STRING
| CHAR
|
;
TEXT : ~[',\n\r"]+ ;
STRING : '"' ('""'|~'"')* '"' ; // quote-quote is an escaped quote
/** Convert 3-char 'x' input sequence to string x */
CHAR: '\'' . '\'' {setText( String.valueOf(getText().charAt(1)) );} ;
编译工作:
$> javac CSV*.java
现在使用匹配的奇怪csv文件进行测试:
a,b
"y",'4'
如:
$> grun CSV file foo.csv
line 1:0 no viable alternative at input 'a'
line 1:2 no viable alternative at input 'b'
header: 'a,b'
values = {a="y", b=4}
1 rows
row token interval: 4..7
总而言之,我建议重写语法的逻辑(我认为插入“BlahBlahBlah”不是必要的,而只是调试黑客)。
并引用http://www.antlr.org/support.html:
ANTLR讨论
Please do not start discussions at stackoverflow. They have asked us to
steer discussions (i.e., non-questions/answers) away from Stackoverflow; we
have a discussion forum at Google specifically for that:
https://groups.google.com/forum/#!forum/antlr-discussion
We can discuss ANTLR project features, direction, and generally argue about
whatever we want at the google discussion forum.
我希望这会有所帮助。
答案 1 :(得分:2)
这里有几个问题:
首先,必须识别field : TEXT { $TEXT.setText("BlahBlah"); }
| STRING
;
方法的接收者。可能想要
setText
其次,Token
类中未定义CommonToken
。
通常,创建自己的扩展TokenLableType
和相应令牌工厂类的令牌类。将setText
(在选项块中)设置为您的令牌类名称。然后,CommonToken
中的AssignFile(myFile, 'Test.txt');
Reset(myFile);
while not Eof(myFile) do
begin
ReadLn(myFile, text);
Richedit.lines.add(myFile);
end;
CloseFile(myFile);
end;
方法将可见。