The YACC metalanguage has a form similar to that for LEX:
%%
Rules <-- BNF plus associated actions
%%
User-Written Procedures <-- In C
The Rules section contains the BNF. The left-hand side is separated from the right-hand side by a color, ":". The actions may appear interspersed in the right-hand side; this means they will be executed when all the tokens or nonterminals to the action's left are shifted. If the action occurs after a production, it will be invoked when a reduction ( of the right-hand side to the left-hand side of a production ) is made.
Thus, a YACC input file looks like the following:
%{
#include 1
#include 2
#define ...
%}
%token ...
...
%%
Nonterminal: Right-Hand side {semantic action 1}
| Right-hand side {semantic action 2}
...
%%
C functions
Example 6 shows a YACC input file for the language consisting of sequences of assignment statements.
EXAMPLE 6 Sequences of assignment statements in YACC
%{
#include <stdio.h>
%}
%start program
%token Id
%token Lit
%%
Program: Statements {printf("Program \n");};
Statements: Statement Statements {printf("Statements \n)";};
| Statement {printf("Statements \n");};
Statement: AsstStmt {printf("Statement \n");};
AsstStmt: Id ":=" Expression {printf("AsstStmt \n");};
Expression: Expression "=" Term {printf("Expression \n");};
| Expression "-" Term {printf("Expression \n");};
| Term {printf("Expression \n");};
Term: Term "*" Factor {printf("Term \n");};
| Term "/" Factor {printf("Term \n");};
| Factor {printf("Term \n");};
Factor: "(" Expression ")" {printf("Factor \n");};
| Id {printf("Factor \n");};
| Lit {printf("Factor \n");};
%%
#include lex.yy.c
main()
{
yyparse ();
}
In Example 6, the lexical analyzer is the one output by LEX, or users
may write their own ( and call it "lex.yy.c"). Alternatively, a function
called "yylex()", consisting of code to find tokens, could be written in
either the definition section or the User-Written Procedures section.
YACC contain facilities for specifying precedence and associativity of operators and for specifying errors. An error production in YACC is of the form:
B
error
{ Action }
where
is an erroneous construct.
We will look at this example again in Chapter 6 when we discuss semantic analysis.