A First Example


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 ::=

      |  "-" 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);
      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
   lex gen.l
   yacc gen.y
   cc -o calc       \
      calc.c        \
      lex.yy.c      \
      y.tab.c       \
      $LIB/errmsg.o \
      $LIB/main.o   \
can be used to create the calculator program calc.

Here the command

   $GENTLE calc.g
invokes 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

invokes 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.y
invoke 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   \
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

then the command

   calc testfile
emits 14 .