HANDBOOK / GETTING STARTED /

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

             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.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

       $REFLEX

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   \
          $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*4

then the command

       calc testfile

emits `14` .