Next: Rpcalc Main, Previous: Rpcalc Rules, Up: RPN Calc [Contents][Index]
rpcalc
Lexical AnalyzerThe lexical analyzer’s job is low-level parsing: converting characters
or sequences of characters into tokens. The Bison parser gets its
tokens by calling the lexical analyzer. See The Lexical
Analyzer Function yylex
.
Only a simple lexical analyzer is needed for the RPN
calculator. This
lexical analyzer skips blanks and tabs, then reads in numbers as
double
and returns them as NUM
tokens. Any other character
that isn’t part of a number is a separate token. Note that the token-code
for such a single-character token is the character itself.
The return value of the lexical analyzer function is a numeric code which
represents a token type. The same text used in Bison rules to stand for
this token type is also a C expression for the numeric code for the type.
This works in two ways. If the token type is a character literal, then its
numeric code is that of the character; you can use the same
character literal in the lexical analyzer to express the number. If the
token type is an identifier, that identifier is defined by Bison as a C
macro whose definition is the appropriate number. In this example,
therefore, NUM
becomes a macro for yylex
to use.
The semantic value of the token (if it has one) is stored into the
global variable yylval
, which is where the Bison parser will look
for it. (The C data type of yylval
is YYSTYPE
, whose value
was defined at the beginning of the grammar via ‘%define api.value.type
{double}’; see Declarations for rpcalc
.)
A token type code of zero is returned if the end-of-input is encountered. (Bison recognizes any nonpositive value as indicating end-of-input.)
Here is the code for the lexical analyzer:
/* The lexical analyzer returns a double floating point number on the stack and the token NUM, or the numeric code of the character read if not a number. It skips all blanks and tabs, and returns 0 for end-of-input. */ #include <ctype.h>
int yylex (void) { int c; /* Skip white space. */ while ((c = getchar ()) == ' ' || c == '\t') continue;
/* Process numbers. */ if (c == '.' || isdigit (c)) { ungetc (c, stdin); scanf ("%lf", &yylval); return NUM; }
/* Return end-of-input. */ if (c == EOF) return 0; /* Return a single char. */ return c; }
Next: Rpcalc Main, Previous: Rpcalc Rules, Up: RPN Calc [Contents][Index]