尝试在lex&中创建简单的解析器YACC

时间:2016-12-27 23:21:58

标签: bison yacc lex

我正在开发一个lex / yacc c编译器。 为了处理失败和解析错误,我想部署一个异常系统处理程序。

实际上,无论出现什么问题,都只会处理“解析错误”消息。例如

这是lex文件

Boolean         [true]|[false]
Char        '[\41-\176]'
Integer     ({Digit)|{Hex}|{Decimal}|{Octal}|{Binary})+
String      \"[^"\n]*\"
Intptr          \"[intptr]
Charptr     \"[charptr]
If      \"[if]
Else        \"[else]
While       \"[while]
Var         \var({Space})({Letter}+)({Variables})({Space})\:  ({Space})
Procedure   \"[procedure]
Return      \"[return]
Null        null
Uppercase      [A-Z]
Letter          [a-zA-Z]
Notchar     "{Letter}"
Digit           [0-9]
Decimal         ([1-9]{Digit})*|[0]
Hex             0[X|x][0-9A-F]+
Octal           [0]([1-7][0-7]*)
Binary          (0|1)+"b"
String1         ({Letter}|{Digit}|{Char})*
Stringerror     \"[^\n]*\"
VALUE       [|]{Integer}[|]
LENGTHSTRING    [|]{String}[|]
Enter       [\15]+
Space       [ \t\r]*
Newline         \n
Type        [{Boolean}|{Integer}|{Var}|{String}]
Typeptr     {Charptr}|{Intptr}
Identifier      {Letter}({Letter}|{Digit}"_")+
Comment     \/\%({String1}|{Space})*\%\/
Variables       (\,{Letter}+)*{Type}\;
%{
%}
%%
Boolean     {return BOOLEAN;}
Integer     {return INTEGER;}
Digit       {return DIGIT;}
Char        {return CHAR;}
Enter       {return ENTER;}
Space       {return SPACE;}
Letter      {return LETTER;}
Newline     {return NEWLINE;}
Type        {return TYPE;}
Typeptr     {return TYPEPTR;}
String      {return STRING;}
Stringerror {return STRINGERROR;}
Notchar     {return NOTCHAR;}
Identifier  {return ID;}
Hex     {return HEX;}
Binary      {return BINARY;}
Decimal     {return DECIMAL;}
Octal       {return OCTAL;}
Comment     {return COMMENT;}
Variables   {return VARIABLES;}
If      {return IF;}
Else        {return ELSE;}
While       {return WHILE;}
Var     {return VAR;}
Procedure   {return PROCEDURE;}
[0-9]+      {return NUM;}
"=="        {return EQ;}
"&&"        {return AND;}
"/"         {return DIVISION;}
"="         {return ASSIGN;}
">"         {return GREATER;}
">="        {return GREATEREQ;}
"<="        {return LESSEQ;}
"<"         {return LESS;}
"-"         {return MINUS;}
"!"         {return NOT;}
"!="        {return NOTEQUAL;}
"||"        {return OR;}
"|"         {return ABSUOLUT;}
"+"         {return PLUS;}
"*"         {return MUL;}
"&"         {return ADDRESS;}
"^"         {return DEREFERENCE;}
"'"         {return SINGLEQUETE;}
";"         {return SEMICOLON;}
":"         {return COLUMS;}
"("         {return LP;}
")"         {return RP;}
"}"         {return RB;}
"{"     {return LB;}
","         {return COMMA;}
.       {return yytext[0];}
%%

和yacc文件:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char* token;
struct node* left;
struct node* right;
}node;
node* mknode(char* token,node* left, node* right);
void printtree(node* tree);
#define YYSTYPE struct node*
%}
%start s
%token BOOLEAN STRING STRINGERROR CHAR NOTCHAR IDENTIFIER INTEGER
%token DIGIT LETTER NEWLINE TYPE TYPEPTR VARIABLES PROCEDURE
%token HEX BINARY DECIMAL OCTAL
%token IF ELSE WHILE COMMENT ENTER SPACE VAR  
%token NUM ASSIGN GREATER GREATEREQ LESSEQ LESS MINUS PLUS MUL DIVISION
%token NOT NOTEQUAL OR ABSUOLUT ADDRESS DEREFERENCE
%token SINGLEQUETE SEMICOLON COLUMS LP RP RB LB COMMA AND
%left NUM
%left AND
%left DIVISION
%left ASSIGN
%left GREATER
%left GREATEREQ
%left LESSEQ
%left LESS
%left MINUS
%left NOT
%left NOTEQUAL
%left OR
%left ABSUOLUT
%left PLUS
%left MUL
%left ADDRESS
%left DEREFERENCE
%left SINGLEQUETE
%left SEMICOLON
%left COLUMS
%left LP RP RB LB
%left COMMA
%%
s:exp {printf("OK\n"); printtree($1);}
exp:
  exp AND exp {$$=mknode("&&",$1,$3);}
| exp DIVISION exp {$$=mknode("/",$1,$3);}
| exp ASSIGN exp {$$=mknode("=",$1,$3);}
| exp GREATER exp {$$=mknode(">",$1,$3);}
| exp GREATEREQ exp {$$=mknode(">=",$1,$3);}
| exp LESSEQ exp {$$=mknode("<=",$1,$3);}
| exp LESS exp {$$=mknode("<",$1,$3);}
| exp MINUS exp {$$=mknode("-",$1,$3);}
| exp NOT exp {$$=mknode("!",$1,$3);}
| exp NOTEQUAL exp {$$=mknode("!=",$1,$3);}
| exp OR exp {$$=mknode("||",$1,$3);}
| exp ABSUOLUT exp {$$=mknode("|",$1,$3);}
| exp PLUS exp {$$=mknode("+",$1,$3);}
| exp MUL exp {$$=mknode("*",$1,$3);}
| exp ADDRESS exp {$$=mknode("&",$1,$3);}
| exp DEREFERENCE exp {$$=mknode("^",$1,$3);}
| exp SINGLEQUETE exp {$$=mknode("'",$1,$3);}
| exp SEMICOLON exp {$$=mknode(";",$1,$3);}
| exp COLUMS exp {$$=mknode(":",$1,$3);}
| exp LP exp {$$=mknode("(",$1,$3);}
| exp RP exp {$$=mknode(")",$1,$3);}
| exp LB exp {$$=mknode("{",$1,$3);}
| exp RB exp {$$=mknode("}",$1,$3);}
| exp COMMA exp {$$=mknode(",",$1,$3);}
| NUM {$$=mknode(yytext,NULL,NULL);}
%%
#include "lex.yy.c"
main()
{
return yyparse();
}
node* mknode(char* token,node* left,node* right)
{
node *newnode=(node*) malloc (sizeof(node));
char *newstr=(char*) malloc (sizeof(token)+1);
strcpy(newstr,token);
newnode->left=left;
newnode->right=right;
newnode->token=newstr;
return newnode;
}
void printtree(node* tree)
{
printf("%s\n",tree->token);
if(tree->left)
  printtree(tree->left);
if(tree->right)
  printtree(tree->right);
}
int yyerror()
{
printf("ERROR\n");
return 0;
}

我尝试编译此代码,我收到此错误和警告:y.tab.c:在

> function ‘yyparse’: y.tab.c:1319:16: warning: implicit declaration of
> function ‘yylex’ [-Wimplicit-function-declaration]
>        yychar = yylex ();
>                 ^ prt2.y:72:21: error: ‘yytext’ undeclared (first use in this function)  | NUM {$$=mknode(yytext,NULL,NULL);}
>                      ^ prt2.y:72:21: note: each undeclared identifier is reported only once for each function it appears in y.tab.c:1604:7:
> warning: implicit declaration of function ‘yyerror’
> [-Wimplicit-function-declaration]
>        yyerror (YY_("syntax error"));
>        ^ prt2.y: At top level: prt2.y:75:1: warning: return type defaults to ‘int’ [-Wimplicit-int]  main()

1 个答案:

答案 0 :(得分:1)

多个问题

  • 你不能在解析器中使用yytext,只能在词法分析器中使用yylex TEMPORARILY 保存当前令牌 - 一旦strdup返回,它就不再有效。因此,您需要在词法分析器操作中复制该字符串(例如,使用yylval)并在[]中返回该字符串。

  • 词法分析器中的
  • [true]|[false]表示字符类,因此像a这样的模式匹配单个字符 - eflrstux' = A * x + t,

相关问题