You are on page 1of 12

LAB SESSION 3

ARITHMETIC EXPRESION EVALUATION


Name: Nguyễn Đức Phi Hồng
ID : ITITIU17022

Principles of Programming Languages Lab 3

1. INTRODUCTION

In Lab 2, we have designed grammar for arithmetic expression. We were also able to
control the precedences and associativities for operations in the expressions. In this lab,
we will have ANTLRWorks evaluate this expression for us. Of course, automatically!

2. OBJECTIVE

The objectives of Lab 3 are (1) to embed attributes and actions to grammar written in
ANTLRWorks and (2) to evaluate arithmetic expression with the embedded information.

3. EXPERIMENT

3.1 Attributes and actions

Let’s begin with a very simple as illustrated in Listing 1.

grammar Lab3;

p : e SEMI;

e : INT;

INT :'0'..'9'+;

SEMI : ';';

Listing 1 – The first grammar.

Nothing is simpler. The grammar accepts only an integer, that’s all.

But now we want the tool to take action. For an arithmetic expression, one may want
nothing more than evaluating the expression value and displaying this value as the output.
Firstly, we will try to print out the value of the inputted integer to the system output. Try
to modify the grammar as presented in Listing 2.

grammar Lab3;

p : e SEMI {System.out.println($e.value);};

e returns [int value]

: INT {$value = Integer.parseInt($INT.text);};

INT :'0'..'9'+;

SEMI : ';';

Listing 2 – An action-embedded grammar.

What we have done in Listing 2 is that we have just added some actions to the grammar.
Not that for your convenience, the actions will be displayed in green color in this paper,
but they will take no particular color in the ANTLRWorks editor.

Consider the following action-embedded rule:

e returns [int value]

: INT {$value = Integer.parseInt($INT.text);};

First of all, this rule is declared returning a value – an integer. The action embedded in
this rule is $value = Integer.parseInt($INT.text); . The $value refers to an attribute named
value of the symbol on the LHS (i.e. e). Thus, the symbols in a grammar rule, including
both non-terminal and terminal ones, can be associated with some attributes. The number
and names of attributes, generally, can be as many as we want.

Similarly, $INT.text refers to the attribute text of the symbol INT. One may just simply
consider this attribute as the lexeme of the symbol INT in the rule.

So, the actual meaning of $value = Integer.parseInt($INT.text); is that the lexeme of INT
will be converted into integral value using the Java utility Integer.parseInt (that means
ANTLRWork can “understand” Java code – interesting revelation, huh?). Then the
converted integer will be assigned to the attribute value of e.
Next, having $e.value evaluated, in the top rule, another Java code is invoked to display
this value to the screen:

p : e SEMI {System.out.println($e.value);};

Well, anything is explained now, but when you try to “run” the grammar as of the old
way, nothing seems different. We only get some parse trees displayed, provided the input
is correct, like 2; or 456;.

3.2 The debugger

In order to perform your actions embedded in the grammar, one must convert them into
binary code and then have the code executed (at least, that what you have learnt in the
lectures, right?). Unfortunately, ANTLR is not a compiler, thus it must rely to a
“professional” compiler like Java to continue processing your actions (i.e. your computer
must have Java installed in advance to perform the following steps). We have many ways
to do this, but let’s start with the simplest one – using the debugger.

You may need to configure your debugger properly before using it. To do it, follow the
menu item path: File->Preferences. In the Compiler tab, enter the path to your javac
program in corresponding textbox and ensure that the checkbox System is checked for
the Classpath variable. It is illustrated in Figure 1.

Figure 1 – Configuring Java parameters for ATNLRWorks

Next, in the Debugger tab, set the default local port as 49153 (if you experience some
port problems when proceeding the rest of the lab, consult your tutor). Now, your
debugger is ready.
To launch the debugger, press the “green bug” icon on the toolbar. If you have not saved
your file beforehand, the debugger will ask you to save you file as a .g file. You must
save your file as the same name with your grammar. For example, if you have defined
your grammar as grammar Lab3;, you .g file MUST be saved as Lab3.g. It is the Java
convention. (I must admit that this convention looks not very smart, but it now belongs to
the history and we can do nothing on it).

When everything is correct, a textbox will appear to prompt you to enter some inputs.
You can either type your input directly or have it read from a file, as showed in Figure 2,
where the input is 4;. Remember to choose the Start Rule properly.

Figure 2 – Setting input for the debugger

The interface of the debugger is quite complex, but what you can do is (1) pressing the
“Go to End” button; (2) browsing the Output tab in Panel-3 (which is automatically
navigated to Debugger tab at the moment) and (3) observing the desired value of 4
displayed in the system output. Everything is indicated in Figure 3. (You can trace your
debugger step-by-step, but if you want to do so, figure out the way yourselves).
Figure 3- The debugger interface.

3.3 Elaborating your grammar

Now you have your grammar “work”. But at the moment, your grammar can only accept
nothing but a single integer. Let’s elaborate it a little bit to accept something more useful.
As seen in Listing 3, your grammar now is enhanced with an operation: the subtraction.

grammar Lab3;

p : e SEMI {System.out.println($e.value);};

e returns [int value]

: INT '-' e {$value = Integer.parseInt($INT.text) - $e.value;}| INT {$value =


Integer.parseInt($INT.text);};
INT :'0'..'9'+;

SEMI : ';';

Listing 3 – The enhanced grammar.

Try to analyze the new grammar yourselves. It is not too hard and quite logical. However,
when you try to launch the debugger, it refuses working. And here is the reason:

e returns [int value] : INT '-' e {$value = Integer.parseInt($INT.text) - $e.value;}

We have two e’s now: one in the LHS, the another in the RHS. And it causes the
confusion in the action part: the debugger cannot resolve which e we want to refer to with
the reference $e.value.

grammar Lab3;

p : e SEMI {System.out.println($e.value);};

e returns [int value]

: INT '-' t = e {$value = Integer.parseInt($INT.text) - $t.value;}| INT {$value =


Integer.parseInt($INT.text);};

INT :'0'..'9'+;

SEMI : ';';

Listing 4 – The enhanced grammar.

Listing 4 presents a simple solution for this problem: alias. To be precise, we declare a
new name of the second e as t and use the new-born t in the action. No ambiguity
anymore!

3.4 Left-recursion again

Your grammar works now with an operation of subtraction. However, this operation is of
right-associativity. But when you want to convert its associativity, we have the left-
recursion again as depicted in Listing 5.
grammar Lab3;

p : e SEMI {System.out.println($e.value);};

e returns [int value]

: t = e '-' INT {$value = $t.value - Integer.parseInt($INT.text);}| INT {$value =


Integer.parseInt($INT.text);};

INT :'0'..'9'+;

SEMI : ';';

Listing 5 – Left-recursion grammar with actions.

In Lab 2, we have known a technique to transform the grammar for eliminating the left-
recursion. However, to embed actions properly into the transformed grammar seems
beyond the capability of ANTLRWorks. Let’s us accept another remedy for this case.

grammar Lab3;

p : e SEMI {System.out.println($e.value);};

e returns [int value]

: i1= INT {$value = Integer.parseInt($i1.text);} ('-' i2=INT {$value -=


Integer.parseInt($i2.text);})*;

INT :'0'..'9'+;

SEMI : ';';

Listing 6 – Handling left-recursion on the grammar.

- Tip: ANTLRWorks can automatically remove the left-recursion (even with actions) for
you, but you should be able to rely on yourselves first.

4. CLASS EXERCISES
a) Modify the grammar Lab3 to accept 4 basic operations of ‘+’, ‘-‘, ‘*’ and ‘/’, in which
‘*’,‘/’ take higher precedences than those of ‘+‘, ‘-’; and all operations are of left-
associativity.

b) Modify grammar in Exercise 4.a such that ‘*’,‘+’ take higher precedences than those
of ‘-‘ ,‘/’; ‘*’, ‘+’ are of left-associativity meanwhile ‘-‘ ,‘/’ are of right-associativity.
c) Modify grammar in Exercise 4.a to accept multiple expressions separated by
semicolon. When running, ANTLRWorks will print out the results of all expressions

For example:

3+4;4+5-6;23-12+47;

the results:
7359

d1) Modify grammar in Exercise 4.a to allow users to use parentheses in the expression.
In addition, the grammar also accepts unary operation of ‘-‘;

For example:

1
For Honor program (KSTN program) only
2-(3----4);

the result:

-5

5. SUBMISSIONS
Students are required to submit in writing to the tutor-in-charge the all of grammars
required in Exercise 4.

You might also like