Antlr環(huán)境配置+計(jì)算器實(shí)現(xiàn)

Reading

Reviewed what has been learned last semester by reading the chapter 1&2 of book Compiler Construction.
Also read Pragmatic.The Definitive ANTLR 4 Reference book and then finished reading the short-course.

Prepare Experiment

I have configured the antlr work environment in two ways.

PowerShell Environment

Download the file from the website, and then move it to a directory for 3rd party java libraries, mine is

C:\javalib

then write two scripts as following.
This is antlr4.bat

@echo off
java org.antlr.v4.Tool %*

And this is grun.bat

@echo off
java org.antlr.v4.gui.TestRig %*

After this two file were all put into system32,
Then we can test it by type command in PowerShell at any position

antlr

and

grun

It seems works fine, then test the example.

Example of Hello

In a test directory, put the following grammar inside file Hello.g4: Hello.g4

// Define a grammar called Hello
grammar Hello;
r  : 'hello' ID ;         // match keyword hello followed by an identifier
ID : [a-z]+ ;             // match lower-case identifiers
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

type

antlr4 Hello.g4

we can see 6 new files named:

  • Hello.tokens
  • HelloBaseListener.java
  • HelloListener.java
  • HelloLexer.java
  • HelloLexer.tokens
  • HelloParser.java

And then compile and test it, I meet thie bug

PS D:\tution\解釋器構(gòu)造\test1> javac *.java
PS D:\tution\解釋器構(gòu)造\test1> grun hello r -tree
Warning: TestRig moved to org.antlr.v4.gui.TestRig; calling automatically
Can't load Hello as lexer or parser

It just seems I forgot to add'.' into the classpath. After add'.' to the class path, it just works well.

IDEA Environment

Just add plugins of antlr4 into this IDE and we can work with it.
create a new file named hello.g4, and then write the same grammer shown above, right click r, choose to test rule r. Then we can see the picture below.


IDEA Environment
IDEA Environment

Calculator

thoughts

Change the thoughts used before, after reading blogs and materials, I found that what I need to do is just define a completed grammar, and then try to to search the abstract grammar tree, and then I can get the calculated outcome.

Grammar

Since the grammar used before is not well-defined, I tried several grammars, and I found a well-defined grammar like below. The discussion of grammars can be found in the foreum(Yeah, it is me :) ).

grammar Calc;

options {
    language=Java;
    output=AST;
    ASTLabelType=CommonTree;
}

// PARSER RULES
prog        : ( ( assign | out ) SEMICOLON)+
            ;
assign      : VAR EQUA expr                     # assignment
            ;
out         : (PRINT '('expr ')' )+             # printExpr
            ;

expr        : expr op=(MULT | DIV) expr         # MulDiv
            | expr op=(MINUS |PLUS) expr        # AddSub
            | NUMBER                            # number
            | VAR                               # varaible
            | '(' expr ')'                      # parens
            ;

//LEXER RULES
PRINT       : 'print';
NUMBER      : INT | FLOAT ;
VAR         : [a-zA-Z][a-zA-Z0-9]*;
WHITESPACE  : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ ->skip ;
INT         : [0-9] | [1-9][0-9]+ ;
FLOAT       : [0-9]+ POINT [0-9]+ ;

PLUS        : '+' ;
MINUS       : '-' ;
MULT        : '*' ;
DIV         : '/' ;
SEMICOLON   : ';' ;
EQUA        : '=' ;
POINT       : '.' ;

Parse-Tree Visitor

The symbol '#' is important, like '# assignment' in line 12, this lable let the antlr creater different visit methods for each rule, and we will override these methods to implement the calculator.
When generate java code using antlr, we should add -no-listener option like since we do not need the listener for now. In command line, the commond is like this.

antlr4 -no-listener -visitor Calc.g

In idea, we should set the antlr generation configuration like the picture below

Antlr Generation Configuration
Antlr Generation Configuration

choose to generate the parse tree vistor.
After generated, we can find that in the CalcBaseVisitor.java, there
!Functions in CalcBaseVistor.java
Then we create our own class file to execute the calculate. Like the function shown below:

//Still need a hashmap to record all the variables to check if they are used before declared.
Map<String, BigDecimal > memory = new HashMap<String,BigDecimal>();

public BigDecimal visitAssignment(CalcParser.AssignmentContext ctx) {
        String var = ctx.VAR().getText();
        BigDecimal value = visit(ctx.expr());
        memory.put(var, value);

        return value;
}

I tried to use the BigDecimal class to fix the precision problem of the float number, but for now I still can not fix it out. And we can see all I did in this function and others is just use the ctx created already , and visit it, do calculation. And we also need to add some codes to check bugs like divition of zero etc.

Main Function

The most important code in the main function is shown like below

// This method seems to be deprecated, but still can be used for now
ANTLRInputStream input = new ANTLRInputStream(is);
// create a lexer
CalcLexer lexer = new CalcLexer(input);
// record all the tokens  
CommonTokenStream tokens = new CommonTokenStream(lexer);
// do parse work to tokens 
CalcParser parser = new CalcParser(tokens);
// create Parse-Tree
ParseTree tree = parser.prog();
// visit the Parse Tree
EvalVistor eval = new EvalVistor();
eval.visit(tree);

Test

After all of whork mentioned above, we finally create a calculator support decimal calculation. Then we can test use the test cases used in last semester
In test.in

a=(10.44*356+1.28)/2+1024*1.6;
b=a*2-a/2;
c123=a+b*b/5-(a-a*2)/b;
print(a);
print(b);
print(c123);
print(1+2-3*4/5);

The output is like below


output for test.in
output for test.in

And error1.in, it miss a semicolon

a=(10.44*356+1.28)/2+1024*1.6;
b=a*2-a/2
print(a);
print(b);

The output is like below
output for error1.in
output for error1.in

error2.in divid zero

a=(10.44*356+1.28)/2-1024*1.6;
print(a);
print(1/0);

The output is like below


output for error2.in
output for error2.in
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 11,047評論 0 23
  • “我愛荒野的彌漫,愛暴雨前的風(fēng)起,獨(dú)不愛行這人間的道。”少年唱到,他獨(dú)特的嗓音配合著吉他像是黑夜中的太陽。 灌了口...
    魚帽貓閱讀 402評論 -1 12
  • 七月、安生,多么動聽的名字。初聽到《七月與安生》這個(gè)名字時(shí),我以為是在七月這個(gè)月份發(fā)生的一場關(guān)于青春的故事??墒牵?..
    遺忘的罐罐閱讀 383評論 6 4
  • 近日在微博上看到一篇文章,是關(guān)于“被頂替上學(xué)者”王娜娜。根據(jù)文章信息所示,王娜娜本于2003年被一所職業(yè)技術(shù)學(xué)院錄...
    三米GZ閱讀 358評論 0 0
  • 價(jià)值投資之父巴菲特的老師格雷厄姆有句區(qū)分投資和投機(jī)的經(jīng)典語句: 如果買入時(shí)就想著有人從自己手里以更好的價(jià)格買去的話...
    陳姿依閱讀 1,704評論 4 24

友情鏈接更多精彩內(nèi)容