如何使用yacc生成c语言语法
时间: 2023-06-27 19:05:50 浏览: 90
分析器?
要使用 yacc 生成 C 语言的语法分析器,需要以下步骤:
1. 编写一个语法描述文件,也称为 .y 文件,用来定义语言的语法结构和相应的语义动作。
2. 使用 yacc 工具来将该语法描述文件编译生成相应的 C 语言代码。
3. 编译上一步中生成的 C 语言代码并运行,即可使用生成的语法分析器来解析相应的代码。
具体使用方法请参考 yacc 工具的使用手册或者相关教程。
相关问题
使用lex,yacc实现C语言的词法分析、语法分析,最后输出抽象语法树(AST),不要求typedef,#define复杂语法,给出完整详细的lex代码和yacc代码
本问题所需的代码较为复杂,无法在此处全部展示。以下是一个简化版本,供参考:
1. Lex代码:
```
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
%}
%%
"int" { return INT; }
"float" { return FLOAT; }
"char" { return CHAR; }
"double" { return DOUBLE; }
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"for" { return FOR; }
"do" { return DO; }
"return" { return RETURN; }
[0-9]+ { yylval.num = atoi(yytext); return NUM; }
[a-zA-Z_][a-zA-Z0-9_]* { yylval.str = strdup(yytext); return ID; }
"==" { return EQ; }
"!=" { return NE; }
">=" { return GE; }
"<=" { return LE; }
">" { return GT; }
"<" { return LT; }
"=" { return ASSGN; }
"+" { return PLUS; }
"-" { return MINUS; }
"*" { return MULT; }
"/" { return DIV; }
"%" { return MOD; }
"(" { return LPAREN; }
")" { return RPAREN; }
"{" { return LBRACE; }
"}" { return RBRACE; }
";" { return SEMICOLON; }
"," { return COMMA; }
"[" { return LBRACKET; }
"]" { return RBRACKET; }
"'" { return SQUOTE; }
\" { return DQUOTE; }
[ \t\n] ; /* ignore white space */
. { printf("Unknown token: %s\n", yytext); }
%%
int yywrap() {
return 1;
}
```
2. Yacc代码:
```
%{
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
%}
%union {
int num;
char *str;
Node *node;
}
%token <num> NUM
%token <str> ID
%token INT FLOAT CHAR DOUBLE IF ELSE WHILE FOR DO RETURN
%token EQ NE GE LE GT LT ASSGN PLUS MINUS MULT DIV MOD LPAREN RPAREN LBRACE RBRACE SEMICOLON COMMA LBRACKET RBRACKET SQUOTE DQUOTE
%type <node> program decl_list decl var_list var stmt_list stmt expr term factor
%start program
%%
program: decl_list {
$$ = create_node(PROGRAM, $1, NULL, NULL);
}
decl_list: /* empty */ {
$$ = NULL;
}
| decl_list decl {
$$ = create_node(DECL_LIST, $1, $2, NULL);
}
decl: type var_list SEMICOLON {
$$ = create_node(DECL, $1, $2, NULL);
}
type: INT {
$$ = create_node(TYPE, "int", NULL, NULL);
}
| FLOAT {
$$ = create_node(TYPE, "float", NULL, NULL);
}
| CHAR {
$$ = create_node(TYPE, "char", NULL, NULL);
}
| DOUBLE {
$$ = create_node(TYPE, "double", NULL, NULL);
}
var_list: var {
$$ = create_node(VAR_LIST, $1, NULL, NULL);
}
| var_list COMMA var {
$$ = create_node(VAR_LIST, $1, $3, NULL);
}
var: ID {
$$ = create_node(VAR, $1, NULL, NULL);
}
| ID LBRACKET NUM RBRACKET {
$$ = create_node(VAR, $1, create_node(NUMBER, $3, NULL, NULL), NULL);
}
stmt_list: /* empty */ {
$$ = NULL;
}
| stmt_list stmt {
$$ = create_node(STMT_LIST, $1, $2, NULL);
}
stmt: expr SEMICOLON {
$$ = create_node(EXPR_STMT, $1, NULL, NULL);
}
| LBRACE stmt_list RBRACE {
$$ = create_node(BLOCK, $2, NULL, NULL);
}
| IF LPAREN expr RPAREN stmt {
$$ = create_node(IF_STMT, $3, $5, NULL);
}
| IF LPAREN expr RPAREN stmt ELSE stmt {
$$ = create_node(IF_ELSE_STMT, $3, $5, $7);
}
| WHILE LPAREN expr RPAREN stmt {
$$ = create_node(WHILE_STMT, $3, $5, NULL);
}
| FOR LPAREN expr SEMICOLON expr SEMICOLON expr RPAREN stmt {
$$ = create_node(FOR_STMT, create_node(EXPR_STMT, $3, NULL, NULL), create_node(EXPR_STMT, $5, NULL, NULL), create_node(EXPR_STMT, $7, NULL, NULL), $9);
}
| DO stmt WHILE LPAREN expr RPAREN SEMICOLON {
$$ = create_node(DO_WHILE_STMT, $4, $2, NULL);
}
| RETURN expr SEMICOLON {
$$ = create_node(RETURN_STMT, $2, NULL, NULL);
}
expr: term {
$$ = create_node(EXPR, $1, NULL, NULL);
}
| expr PLUS term {
$$ = create_node(PLUS_EXPR, $1, $3, NULL);
}
| expr MINUS term {
$$ = create_node(MINUS_EXPR, $1, $3, NULL);
}
term: factor {
$$ = create_node(TERM, $1, NULL, NULL);
}
| term MULT factor {
$$ = create_node(MULT_TERM, $1, $3, NULL);
}
| term DIV factor {
$$ = create_node(DIV_TERM, $1, $3, NULL);
}
| term MOD factor {
$$ = create_node(MOD_TERM, $1, $3, NULL);
}
factor: NUM {
$$ = create_node(NUMBER, $1, NULL, NULL);
}
| ID {
$$ = create_node(IDENTIFIER, $1, NULL, NULL);
}
| ID LBRACKET expr RBRACKET {
$$ = create_node(ARRAY_ACCESS, $1, $3, NULL);
}
| LPAREN expr RPAREN {
$$ = create_node(EXPR, $2, NULL, NULL);
}
| MINUS factor {
$$ = create_node(NEG_FACTOR, $2, NULL, NULL);
}
| factor PLUS PLUS {
$$ = create_node(POST_INC_FACTOR, $1, NULL, NULL);
}
| factor MINUS MINUS {
$$ = create_node(POST_DEC_FACTOR, $1, NULL, NULL);
}
| SQUOTE ID SQUOTE {
$$ = create_node(CHARACTER, $2, NULL, NULL);
}
| DQUOTE ID DQUOTE {
$$ = create_node(STRING, $2, NULL, NULL);
}
| func_call {
$$ = create_node(EXPR_STMT, $1, NULL, NULL);
}
func_call: ID LPAREN arg_list RPAREN {
$$ = create_node(FUNC_CALL, $1, $3, NULL);
}
arg_list: /* empty */ {
$$ = NULL;
}
| expr {
$$ = create_node(ARG_LIST, $1, NULL, NULL);
}
| arg_list COMMA expr {
$$ = create_node(ARG_LIST, $1, $3, NULL);
}
%%
int yylex();
void yyerror(char *);
int main() {
yyparse();
return 0;
}
void yyerror(char *s) {
printf("%s\n", s);
}
```
以上代码演示了如何使用lex和yacc实现C语言的词法分析、语法分析,并输出抽象语法树。具体实现中还需要定义Node结构体和相关的操作函数,以及将yacc生成的AST传递到下一步的代码生成中。
使用lex和yacc编写一个C语言的语法分析器
1. 创建lex文件,命名为c_lex.l,输入以下内容:
%{
#include "c_yacc.tab.h"
%}
%%
"int" { return INT; }
"float" { return FLOAT; }
"char" { return CHAR; }
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"for" { return FOR; }
"return" { return RETURN; }
[0-9]+ { yylval.num = atoi(yytext); return NUM; }
[a-zA-Z_][a-zA-Z0-9_]* { yylval.id = strdup(yytext); return ID; }
";" { return SEMICOLON; }
"," { return COMMA; }
"(" { return LEFTPAREN; }
")" { return RIGHTPAREN; }
"{" { return LEFTBRACE; }
"}" { return RIGHTBRACE; }
"==" { return EQ; }
">" { return GT; }
">=" { return GE; }
"<" { return LT; }
"<=" { return LE; }
"!=" { return NE; }
"=" { return ASSIGN; }
"//" { while(yyinput() != '\n'); }
"/*" { while(yyinput() != '*' || yyinput() != '/') yyinput(); }
[ \t\n] { }
. { printf("Error: unknown character %c\n", *yytext); }
%%
int yyinput(void)
{
return fgetc(yyin);
}
2. 创建yacc文件,命名为c_yacc.y,输入以下内容:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int yylex();
void yyerror(char *error);
int yyparse();
extern FILE *yyin;
extern int yylineno;
extern char *yytext;
%}
%token INT FLOAT CHAR IF ELSE WHILE FOR RETURN
%token NUM ID
%token SEMICOLON COMMA LEFTPAREN RIGHTPAREN LEFTBRACE RIGHTBRACE
%token EQ GT GE LT LE NE ASSIGN
%start program
%%
program: statement
;
statement: declaration
| assignment
| if_statement
| while_statement
| for_statement
| return_statement
| SEMICOLON
;
declaration: type ID SEMICOLON
;
assignment: ID ASSIGN expression SEMICOLON
;
if_statement: IF LEFTPAREN expression RIGHTPAREN LEFTBRACE statement RIGHTBRACE
| IF LEFTPAREN expression RIGHTPAREN LEFTBRACE statement RIGHTBRACE ELSE LEFTBRACE statement RIGHTBRACE
;
while_statement: WHILE LEFTPAREN expression RIGHTPAREN LEFTBRACE statement RIGHTBRACE
;
for_statement: FOR LEFTPAREN expression SEMICOLON expression SEMICOLON expression RIGHTPAREN LEFTBRACE statement RIGHTBRACE
;
return_statement: RETURN expression SEMICOLON
;
type: INT
| FLOAT
| CHAR
;
expression: expression EQ expression
| expression GT expression
| expression GE expression
| expression LT expression
| expression LE expression
| expression NE expression
| expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression
| LEFTPAREN expression RIGHTPAREN
| ID
| NUM
;
%%
void yyerror(char *error)
{
printf("Error: %s at line %d\n", error, yylineno);
}
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if(!fp)
{
printf("Error: cannot open file %s\n", argv[1]);
return 1;
}
yyin = fp;
yyparse();
fclose(fp);
return 0;
}
3. 编译生成可执行文件,输入以下命令:
lex c_lex.l
yacc -d c_yacc.y
gcc lex.yy.c y.tab.c -o c_parser
4. 执行可执行文件,并输入要分析的C语言代码文件名,例如:
./c_parser test.c
其中test.c为要分析的C语言代码文件。
阅读全文
相关推荐














