从基础开始 yacc 实际上非常易于使用。只要提供给它一组描述语法的规则,它就可以分析标记,并根据所见到的采取操作。对于我们使用的脚本语言,我们希望由浅入深,最初只是指定一些数字及其逻辑运算:
%{
/* This first section contains C code which will be included in the output
file.
*/
#include <stdlib.h>
#include <stdio.h>
/* Since we are using C++, we need to specify the prototypes for some
internal yacc functions so that they can be found at link time.
*/
extern int yylex(void);
extern void yyerror(char *msg);
%}
/* This is a union of the different types of values that a token can
take on. In our case we'll just handle "numbers", which are of
C int type.
*/
%union {
int number;
}
/* These are untyped tokens which are recognized as part of the grammar */
%token AND OR EQUALS
/* Here we are, any NUMBER token is stored in the number member of the
union above.
*/
%token NUMBER
/* These rules all return a numeric value */
%type expression
%type logical_expression and or equals
%%
/* Our language consists either of a single statement or of a list of statements.
Notice the recursivity of the rule, this allows us to have any
number of statements in a statement list.
*/
statement_list: statement | statement_list statement
;
/* A statement is simply an expression. When the parser sees an expression
we print out its value for debugging purposes. Later on we'll
have more than just expressions in our statements.
*/
statement: expression
{ printf("Expression = %d/n", $1); }
;
/* An expression can be a number or a logical expression. */
expression: NUMBER
| logical_expression
;
/* We have a few different types of logical expressions */
logical_expression: and
| or
| equals
;
/* When the parser sees two expressions surrounded by parenthesis and
connected by the AND token, it will actually perform a C logical
expression and store the result into
this statement.
*/
and: '(' expression AND expression ')'
{ if ( $2 && $4 ) { $ = 1; } else { $ = 0; } }
;
or: '(' expression OR expression ')'
{ if ( $2 || $4 ) { $ = 1; } else { $ = 0; } }
;
equals: '(' expression EQUALS expression ')'
{ if ( $2 == $4 ) { $ = 1; } else { $ = 0; } }
;
%%
/* This is a sample main() function that just parses standard input
using our yacc grammar. It allows us to feed sample scripts in
and see if they are parsed correctly.
*/
int main(int argc, char *argv[])
{
yyparse();
}
/* This is an error function used by yacc, and must be defined */-
void yyerror(char *message)
{
fprintf(stderr, "%s/n", message);
}
33万+

被折叠的 条评论
为什么被折叠?



