Java中的ANTLR基本示例

mar*_*ike 0 java compiler-construction antlr

我过去几个小时一直在网上搜索,试图学习一个使用ANTLR的简单例子.但是我很难理解这些例子.是否有任何正文可以在Java中输出:

如果我的意见是 printf("Hello World");

输出应该是:

你好,世界

如果我的意见是

inx = 1;

它应该给出一条错误信息.

我正在尝试使用java创建一个c ++编译器(从词汇开始直到语义部分),我真的想知道我应该做什么.

cco*_*ley 5

这是一个几乎完成你想要的语法:

grammar PrintLang;

sentence 
    :    statement
    ;

statement 
    :   functionCall '(' argument ')' ';'
    { 
      if ($functionCall.funName.equals("printf")) {
        System.out.println($argument.arg);
      }
    }
    ;

functionCall returns [String funName]
    :    ID 
    { $funName = $ID.text; }
    ;

argument returns [String arg]
    :   STRING
    { $arg = $STRING.text; }
    ;

ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

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

STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;
Run Code Online (Sandbox Code Playgroud)

我在AntlrWorks中生成了这个.所有令牌规则都是为我生成的.

这是测试它的java文件.

import org.antlr.runtime.*;


public class PrintIt {
  public static void main(String args[]) {
    String inputString = "printf(\"HelloWorld\");";

    // Create an input character stream from standard in
    ANTLRStringStream input = new ANTLRStringStream(inputString); 
    // Create an ExprLexer that feeds from that stream 
    PrintLangLexer lexer = new PrintLangLexer(input);
    // Create a stream of tokens fed by the lexer 
    CommonTokenStream tokens = new CommonTokenStream(lexer); 
    // Create a parser that feeds off the token stream 
    PrintLangParser plParser = new PrintLangParser(tokens);
    try {
        plParser.sentence();
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

你会注意到这个java代码几乎是来自Antlr网站示例的逐字复制/粘贴(我不相信我甚至改变了注释,这就是注释引用Standard的原因,但代码实际上使用了String) .这是我过去使用的命令行.

bash$ java -cp ./antlr-3.4-complete.jar org.antlr.Tool PrintLang.g
bash$ javac -cp ./:./antlr-3.4-complete.jar PrintIt.java 
bash$ java -cp antlr-3.4-complete.jar:. PrintIt
"HelloWorld"
Run Code Online (Sandbox Code Playgroud)

哎呀,我忘了我要打印的字符串不是匹配的标记("HelloWorld",包括引号),它是引号内的字符串.

另外,您会注意到我将printf的查找硬编码为字符串比较.实际上,您需要一个包含在给定范围内可访问的符号的环境(相关,请参阅antlr的"范围"构造.更难,但有时有用:创建一个传递给每个解析规则的环境).

最重要的是:通过搜索SO找到更多的问题,找到Bart Kiers的答案.他发表了很好的例子.