【问题标题】:ANTLR problem with bindingANTLR 绑定问题
【发布时间】:2010-02-15 17:27:39
【问题描述】:

我有这样的字符串:

`(val1, val2, val3)`

我有 ANTLR 语法来解析这段代码:

grammar TEST;

tokens {
 ORB = '(';
 CRB = ')';
 COMA = ',';
}

@members{

}
/*Parser rule*/
mainRule 
    :    ORB WORD (COMA WORD)* CRB;

/*Lexer rule*/

WORD    :    ('a'..'z'|'A'..'Z'|'0'..'9')+;

WS      :   ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; };

现在我需要将所有WORDs 映射到Java。当目标标记包含在括号中时如何绑定值?

非常感谢!

【问题讨论】:

  • 你提到有几个人给了你有用的答案——投票给这些问题怎么样?

标签: java antlr


【解决方案1】:

与 JS Bangs 的回答几乎相同,只是这里有一个完整的 SSCCE,您可以编译和运行,我展示了如何“标记”您的令牌并访问它们以将它们放入 mainRule 返回的列表中。另请注意,init 前面需要一个 @ 符号(至少 ANTLR v3 需要它)。

grammar Test;

@parser::members {
  public static void main(String[] args) throws Exception {
    String text = "(a, bb ,  ccc )";
    ANTLRStringStream in = new ANTLRStringStream(text);
    TestLexer lexer = new TestLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    System.out.println(new TestParser(tokens).mainRule());
  }
}

mainRule returns [List<String> words]
@init{$words = new ArrayList<String>();}
  :  '(' w=WORD {$words.add($w.text);} (',' w=WORD {$words.add($w.text);} )* ')'
  ;

WORD
  :  ('a'..'z'|'A'..'Z'|'0'..'9')+
  ;

WS
  :  ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; }
  ;

然后:

bart@hades:~/Temp$ java -cp antlr-3.2.jar org.antlr.Tool Test.g
bart@hades:~/Temp$ javac -cp antlr-3.2.jar *.java
bart@hades:~/Temp$ java -cp .:antlr-3.2.jar TestParser
[a, bb, ccc]
bart@hades:~/Temp$ 

在 Windows 上,上述命令几乎相同,只需像这样运行 TestParser

java -cp .;antlr-3.2.jar TestParser

(有一个分号而不是常规冒号)

【讨论】:

  • 谢谢!你的回答对我很有用!
【解决方案2】:

抱歉,您能详细说明一下您要做什么吗? 据我所知,您想将每个单词绑定到一个 java 变量,对吗?

words+=WORD (COMA words+=WORD)* {$words}

在这里您定义一个标签words(实际上是一个列表)并使用+= 语法将WORD 的每个出现添加到该标签。然后你可以参考这个标签,如图$words

查看 ANTLR 文档并查找标签。 如果你想用你的解析器做一些复杂的事情,我推荐 Terrence Parr 的关于 ANTLR 的书。它对解析的一般主题有很好的介绍性章节,是 ANTLR 的最佳参考。

HTH

【讨论】:

  • 谢谢!这正是我的意思!抱歉,问题表述不当,英语不是我的母语
  • 不客气。如果答案对您有帮助,请不要忘记标记它。我不认为 SO-flair 积分在 ebay 上交易(还);-)
【解决方案3】:

您可以使用.text 属性获取匹配标记的文本值。像这样:

 string s = $WORD.text

根据您的整体语法应该做什么,将$WORD.text 字符串添加到内部列表、将其传递给其他函数或将其转换为mainRule 的返回值可能是合适的。例如,如果您希望mainRule 将已解析字符串的列表返回给您,您可以编写以下内容:

mainRule returns [List strings] @init { $strings = new Vector(); }:
    ORB 
    WORD { $strings.add($WORD.text); } 
    ( COMMA WORD { $strings.add($WORD.text); } )*
    CRB
    ;

【讨论】:

  • 不确定您是否忘记了init 之前的@,或者它是否是ANTLR v2 语法。在 ANTLR v3 中,您应该在其前面放置一个 @
  • 谢谢!我不知道@init 关键字。你的回答对我很有帮助。附言您的示例中有一些错误,这是正确的代码: mainRule2 返回 [List strings] @init { $strings = new Vector(); }: ORB val0=WORD { $strings.add($val0.text); } ( COMA val1=WORD { $strings.add($val1.text); } )* CRB;
猜你喜欢
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
相关资源
最近更新 更多