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.