ANTLR笔记1 - 让示例跑起来

安装配置:
1. JDK环境 http://java.sun.com/
   JDK bin路径设置。如果只是生成C#程序,装JRE就可以,生成Java程序,编译测试才需要JDK。网上Java的示例多一些,所以不妨装个Eclipse。
2. 安装ANTLR v3 http://www.antlr.org/download.html
   我没有用ANTLRWorks,下载的ANTLR 3.0.1 source distribution,用命令行生成。解压后antlr-3.0.1\lib目录下的所有jar都需要包括到CLASSPATH中。

Getting started:
按照http://www.antlr.org/wiki/display/ANTLR3/FAQ+-+Getting+Started可以把示例跑起来。

示例1 C#
下面例子取自http://www.antlr.org/wiki/display/ANTLR3/Five+minute+introduction+to+ANTLR+3,生成C#,可以完整run起来,我做了些修改,使得运行后可以看到效果。
1. 建一个工作目录Antlr(名字无所谓)
2. 在工作目录中建立一个SimpleCalc.g语法文件,内容如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> grammar SimpleCalc ;

options {
    language
= CSharp ;
}

tokens {
    PLUS     
=  ' + ;
    MINUS    
=  '-'  ;
    MULT    
=  '*'  ;
    DIV    
=  ' / ;
}

@members {
        static void Main
( string[] args )
        {
            string source 
=  Console . ReadLine ();
            SimpleCalcLexer lex 
=  new SimpleCalcLexer ( new ANTLRStringStream ( source ));
            CommonTokenStream tokens 
=  new CommonTokenStream ( lex );
            SimpleCalcParser parser 
=  new SimpleCalcParser ( tokens );
            try
            {
                Console
. WriteLine ( parser . expr ());
            }
            catch 
( RecognitionException e )
            {
                Console
. Error . WriteLine ( e . StackTrace );
            }
            Console
. ReadLine ();
        }
}

// PARSER RULES
expr returns [int value] :
    e
= term {  $ value =$ e . value ;  }
    
(    
      PLUS e
= term {  $ value  +=   $ e . value ;  }
      |
      MINUS e
= term {  $ value - =   $ e . value ;  }
    
) * ;
term returns [int value] : 
    e
= factor {  $ value  =   $ e . value ;  }
    
(
      MULT e
= factor {  $ value * =   $ e . value ;  }
      |
      DIV e
= factor {  $ value  /=   $ e . value ;  }
    
) ;
factor returns [int value] : NUMBER { 
$ value  =  int . Parse ($ NUMBER . text );  } ;

// LEXER RULES
NUMBER    : 
( DIGIT )+   ;
WHITESPACE : 
(  ' \ t' | ' ' | ' \ r' | ' \ n'| ' \ u000C'  )+      {  $ channel  =  HIDDEN ;  }  ;
fragment DIGIT    : '
0 ' .. ' 9 ;

注意: 语法文件名必须跟grammar指定的名称一致,否则ANTLR生成时会报错error(8):  file *** contains grammar SimpleCalc; names must be identical。
3. 命令行,当前路径为工作目录,运行java org.antlr.Tool SimpleCalc.g。这会在工作目录下生成两个文件SimpleCalcLexer.cs和SimpleCalcParser.cs。
4. 用VS建立一个Console工程,把program.cs删掉,把SimpleCalcLexer.cs和SimpleCalcParser.cs添加到工程中,添加引用antlr-3.0.1\runtime\CSharp\bin\net-2.0\Antlr3.Runtime.dll,编译运行。(一种是只引用Antlr3.Runtime.dll,另一种是引用Antlr3.Utility.dll、antlr.runtime.dll、StringTemplate.dll这3个,看是否需要用到StringTemplate的一些特性而定)
5. 在命令行输入表达式,程序会把结果输出来。因为语法文件简单,所以只能是简单表达式,包含+, -, *, /操作,不能有括号以及其它非数字字符,运算结果必须为整数(尤其针对除法而言)。例如输入3+4*5,结果为23。

示例2 Java:
取自http://www.antlr.org/wiki/display/ANTLR3/Expression+evaluator,同样是一个简单的求值计算示例,可以使用变量。需要有JDK。
1. 在工作目录中建一个语法文件Expr.g,内容如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> grammar Expr ;

@header {
import java
. util . HashMap ;
}

@members {
/ ** Map variable name to Integer object holding value * /
HashMap memory 
=  new HashMap ();
}

prog:   stat
+   ;
                
stat:   expr NEWLINE {System
. out . println ($ expr . value ); }
    |   ID '
= ' expr NEWLINE
        {memory
. put ($ ID . text ,  new Integer ($ expr . value )); }
    |   NEWLINE
    
;

expr returns [int value]
    :   e
= multExpr { $ value  =   $ e . value ; }
        
(    ' + ' e = multExpr { $ value  +=   $ e . value ; }
        |   '-' e
= multExpr { $ value - =   $ e . value ; }
        
) *
    
;

multExpr returns [int value]
    :   e
= atom { $ value  =   $ e . value ; ( '*' e = atom { $ value * =   $ e . value ; } ) *
    
;  

atom returns [int value]
    :   INT {
$ value  =  Integer . parseInt ($ INT . text ); }
    |   ID
        {
        Integer v 
=   ( Integer ) memory . get ($ ID . text );
        
if   (  v! = null  )   $ value  =  v . intValue ();
        
else  System . err . println ( " #ff0000 variable  " +$ ID . text );
        }
    |   '
( ' expr ' ) ' { $ value  =   $ expr . value ; }
    
;

ID  :   
( 'a' .. 'z'|'A' .. 'Z' )+   ;
INT :   '
0 ' .. ' 9 ' +   ;
NEWLINE:'
\ r'? ' \ n'  ;
WS  :   
( ' '|' \ t' )+  {skip (); ;

2. 命令行,当前路径为工作目录,运行java org.antlr.Tool Expr.g。这会在工作目录下生成两个文件ExprLexer.java和ExprParser.java。
3. 建立Test.java文件,测试代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> import  org.antlr.runtime. * ;

public   class  Test {
    
public   static   void  main(String[] args)  throws  Exception {
        ANTLRInputStream input 
=   new  ANTLRInputStream(System.in);
        ExprLexer lexer 
=   new  ExprLexer(input);
        CommonTokenStream tokens 
=   new  CommonTokenStream(lexer);
        ExprParser parser 
=   new  ExprParser(tokens);
        parser.prog();
    }
}

4. 编译java文件: javac Test.java ExprLexer.java ExprParser.java。
5. 运行测试: java Test。运行后命令行为等待输入状态,例如输入:
x=1
y=2
3*(x+y)+12
<EOF>
将显示结果为21。在Windows DOS中输入EOF的方法为Ctrl+Z,回车。

猜你喜欢

转载自jackyhongvip.iteye.com/blog/1559103