A parser generator (POSIX)
yacc [-b prefix] [-dltv] file
The yacc utility transforms a specification of a context-free grammar into a C language function that implements an LR(1) parsing algorithm. Ambiguities in the grammar may be resolved using precedence rules within the specification. The C language function is named yyparse(), and calls yylex() to get input tokens, which are integer values. The value 0 is considered special, as being end-of-input.
You can use the following parser with the lexical analyzer in lex to implement a simple calculator.
%{ /* * calculator: a simple calculator. * This calculator allows all common arithmetic operations, * including sin, cos, tan, sqrt, exp, pow, log. * The calculator is a simple example of using the yacc * parser generator. * */ #include <stdio.h> #include <math.h> #define YYSTYPE double YYSTYPE last_value = 0; extern int yylex(void); %} /* * Define the tokens produced by yylex() */ %token NUMBER %token LAST %left '+' '-' %left '*' '/' %left '^' %left NEGATIVE %left COS EXP SIN SQRT TAN /* * Begin specification of the parser. */ %% /* * a 'list' may be empty, contain blank lines or expressions. */ list: | list '\n' | list expr '\n' { printf("%.8g\n",last_value=$2); } ; /* * Expressions are defined recursively as strings of terms * and expressions. Note that the 'sin',... functions do not * require bracketed parameters although sin x +1 is * interpreted as (sin(x))+1 */ expr: term { $$ = $1; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '^' expr { $$ = pow($1,$3); } | '-' expr %prec NEGATIVE { $$ = - $2; } | COS term { $$ = cos($2); } | EXP term { $$ = exp($2); } | SIN term { $$ = sin($2); } | SQRT term { $$ = sqrt($2); } | TAN term { $$ = tan($2); } ; /* * The following are of the highest precedence. * They needed to be distinguished to allow the * functions (sin...) to operate properly without * parentheses */ term: NUMBER { $$ = $1; } | LAST { $$ = last_value; } | '(' expr ')' { $$ = $2; } ; %% #include <stdlib.h> #include <string.h> #include <unistd.h> int lineno; char *fname = "-stdin-"; int yyerror(const char *s) { fprintf(stderr,"%s(%d):%s\n",fname,lineno,s); return 0; } main() { yyparse(); return 0; }
Vern Paxton, The University of California at Berkeley
A.V. Aho and S.C Johnson, "LR Parsing," Computing Surveys, June 1974.
A.V. Aho, R. Sethi, and J.D. Ullman, Compilers: Principles, Techniques, and Tools, Addison-Wesley, 1977.
S.C. Johnson, "Yacc -- Yet Another Compiler-Compiler," Bell Laboratories Computing Science Technical Report # 32, July 1978.
Brian W. Kernighan and Rob Pike, The UNIX Programming Environment, Prentice-Hall, 1984.
J. P. Bennett, Introduction to Compiling Techniques -- A First Course using ANSI C, LEX, and YACC, McGraw-Hill, 1990.
John R. Levine, Tony Mason, and Doug Brown, lex and yacc, O'Reilly and Associates, 1990.