
This section describes how to use the Gentle system to construct a simple desk calculator. This calculator will read (from standard input or from a specified file) an expression according to the following syntax:
expression ::=
expression "+" expr2
| expression "-" expr2
| expr2
expr2 ::=
expr2 "*" expr3
| expr2 "/" expr3
| expr3
expr3 ::=
Number
| "-" expr3
| "+" expr3
| "(" expression ")"
where the token Number represents a sequence of decimal digits.
The program will calculate the value of the expression and print it on
standard output.
Here is a Gentle specification of the calculator (file calc.g). This simply mirrors the above grammar, where each nonterminal has an output parameter that represents its value.
'root' expression(-> X) print(X)
'nonterm' expression(-> INT)
'rule' expression(-> X): expr2(-> X)
'rule' expression(-> X+Y): expression(-> X) "+" expr2(-> Y)
'rule' expression(-> X-Y): expression(-> X) "-" expr2(-> Y)
'nonterm' expr2(-> INT)
'rule' expr2(-> X): expr3(-> X)
'rule' expr2(-> X*Y): expr2(-> X) "*" expr3(-> Y)
'rule' expr2(-> X/Y): expr2(-> X) "/" expr3(-> Y)
'nonterm' expr3(-> INT)
'rule' expr3(-> X): Number(-> X)
'rule' expr3(-> - X): "-" expr3(-> X)
'rule' expr3(-> + X): "+" expr3(-> X)
'rule' expr3(-> X): "(" expression(-> X) ")"
'token' Number(-> INT)
The representation of the token Number is not specified in the Gentle
specification. Instead, we use a token description file from the
reflex directory (file Number.t):
[0-9]+ {
yylval.attr[1] = atoi(yytext);
yysetpos();
return Number;
}
Assume that $GENTLE is the path name for the program gentle,
$GRTS for the Gentle run time system grts.o,
$REFLEX for the program reflex,
and $LIB is the user library.
Then the command sequence
$GENTLE calc.g
$REFLEX
lex gen.l
yacc gen.y
cc -o calc \
calc.c \
lex.yy.c \
y.tab.c \
$LIB/errmsg.o \
$LIB/main.o \
$GRTS
can be used to create the calculator program calc.
Here the command
$GENTLE calc.ginvokes the Gentle compiler, which translates the specification calc.g into a C file calc.c. In addition, it generates some files gen.*, which the user need not bother about.
The command
$REFLEXinvokes the program reflex. This creates a specification for the scanner generator Lex (from files created by gentle and files provided by the user such as Number.t).
The commands
lex gen.l yacc gen.yinvoke the scanner generator Lex and the parser generator Yacc respectively.
Finally, the C compiler creates the program calc:
cc -o calc \
calc.c \
lex.yy.c \
y.tab.c \
$LIB/errmsg.o \
$LIB/main.o \
$GRTS
lex.yy.c and y.tab.c are C files created by Lex and Yacc.
$LIB/errmsg.o and $LIB/main.o are modules from the
user library. They provide an error message routine and and main function
that invokes the code created by the Gentle compiler
(a user may use these components as they are, or adapt them according
to his or her needs).
If testfile contains the line
2+3*4then the command
calc testfileemits 14 .