Bison 使用Flex&;的简单Java语法;野牛

Bison 使用Flex&;的简单Java语法;野牛,bison,flex-lexer,Bison,Flex Lexer,我最近开始学习基本的Flex和Bison,因为我必须为简单(但不是太简单)语法制作解析器。我决定在语法中使用简化的Java语言。我制作了.l和.y文件,所有的东西都编译无误(我使用gcc进行编译)。 问题是,每次运行生成的程序时,我都会得到语法错误,即使是像这样的简单输入:private class Something{}。只有在输入空行(\n)时,我才没有收到语法错误。 我已经为此挣扎了几天,我怀疑我的语法有问题,但我似乎找不到。当然,可能还有其他问题,因为我对Flex和Bison还很陌生 任

我最近开始学习基本的Flex和Bison,因为我必须为简单(但不是太简单)语法制作解析器。我决定在语法中使用简化的Java语言。我制作了
.l
.y
文件,所有的东西都编译无误(我使用gcc进行编译)。 问题是,每次运行生成的程序时,我都会得到
语法错误
,即使是像这样的简单输入:
private class Something{}
。只有在输入空行(
\n
)时,我才没有收到
语法错误。
我已经为此挣扎了几天,我怀疑我的语法有问题,但我似乎找不到。当然,可能还有其他问题,因为我对Flex和Bison还很陌生

任何帮助都将不胜感激

以下是
.l
.y
文件:

java.l

%{
#include "java.tab.h"
%}

%option noyywrap

%%

"\n" return 0;
[ \t] ;

"private" {return PRIVATE;}
"public" {return PUBLIC;}
"protected" {return PROTECTED;}
"implenets" {return IMPLEMENTS;}
"extends" {return EXTENDS;}
"class" {return CLASS;}
"interface" {return INTERFACE;}
"if" {return IF;}
"while" {return WHILE;}
"return" {return RETURN;}
"true" {return BOOLEAN;}
"false" {return BOOLEAN;}

[A-z][a-z0-9]* {return NAME;}

"\""[A-z0-9]*"\"" {return STRING;}
"-"?[1-9][0-9]* {return INT;}

"+"|"-"|"*"|"/"|"="|"==" {return OPERATOR;}

%%
java.y

%{
#include <stdio.h>

int cond=0;
int loops=0;
int assigns=0;
int funcs=0;
int classes=0;

void yyerror(const char* msg){printf("Error: %s\n", msg);}
%}


%token PUBLIC
%token PRIVATE
%token PROTECTED
%token NAME
%token IMPLEMENTS
%token EXTENDS
%token CLASS
%token INTERFACE
%token IF
%token WHILE
%token STRING
%token BOOLEAN
%token OPERATOR
%token RETURN 
%token INT

%%

Code: Class Code | /*empty*/ {printf("classes: %d\n", classes); printf("functions: %d\n", funcs); printf("conditions: %d\n", cond); 
                                printf("loops: %d\n", loops); printf("assign operations: %d\n", assigns);} ;
Class: Modifier ClassType NAME Extra '{' Functions '}' ;
Modifier: PUBLIC | PRIVATE | PROTECTED ;
ClassType: CLASS | INTERFACE ;
Extra: IMPLEMENTS NAME | EXTENDS NAME | /*empty*/ ;
Functions: Function Functions | /*empty*/ ;
Function: Type NAME '(' Arguments ')' '{' Commands '}' {funcs++;} ;
Arguments: Argument Arguments | /*empty*/ ;
Argument: Type NAME Separator ;
Type: STRING | INT | BOOLEAN ;
Separator: ',' | /*empty*/ ;
Commands: Command Commands | /*empty*/ ;
Command: Condition | Loop | Assignment | Return ;
Condition: IF '(' Comparison ')' '{' Commands '}' {cond++;} ;
Loop: WHILE '(' Comparison ')' '{' Commands '}' {loops++;} ;
Comparison: NAME OPERATOR INT | NAME OPERATOR NAME | INT OPERATOR NAME ;
Assignment: NAME '=' Type ';' {assigns++;} ;
Return: RETURN RetVal ';' ;
RetVal: NAME | Type ;

%%

int main()
{
   yyparse();
   return 0;
}
%{
#包括
int cond=0;
int循环=0;
int=0;
int funcs=0;
int类=0;
void yyerror(const char*msg){printf(“错误:%s\n”,msg);}
%}
%代币公众
%私人代币
%令牌保护
%令牌名
%代币工具
%令牌扩展
%令牌类
%令牌接口
%代币如果
%代币
%令牌串
%标记布尔
%代币操作员
%代币返还
%标记整数
%%
代码:类代码|/*空*/{printf(“类:%d\n”,类);printf(“函数:%d\n”,funcs);printf(“条件:%d\n”,cond);
printf(“循环:%d\n”,循环);printf(“分配操作:%d\n,分配”);};
类:修饰符类类型名称额外“{”函数“}”;
修饰语:公共|私人|保护;
类类型:类|接口;
额外:实现名称|扩展名称|/*空*/;
函数:函数函数|/*空*/;
函数:类型名称“('Arguments')”{'Commands'}{funcs++;};
参数:参数参数|/*空*/;
参数:类型名称分隔符;
类型:字符串| INT |布尔值;
分隔符:','|/*空*/;
命令:命令命令|/*空*/;
命令:条件|循环|赋值|返回;
条件:如果“('Comparison')”{'Commands'}{cond++;};
循环:WHILE'('Comparison')'{'Commands'}'{loops++;};
比较:NAME OPERATOR INT | NAME OPERATOR NAME | INT OPERATOR NAME;
分配:名称“=”类型“;”{assigns++;};
Return:Return RetVal';';
RetVal:NAME | Type;
%%
int main()
{
yyparse();
返回0;
}
这是一个开始:

首先,
flex
提供的默认规则只是回显任何其他规则都无法匹配的字符
{
}
没有任何规则匹配,因此bison将回显它们,并且永远看不到它们,这使得生产
无法匹配。一个简单的解决方案是将默认规则作为最后一个
flex
规则:

. { return yytext[0]; }
其次,
[A-z]
[A-Za-z]
不同,因为
z
A
在ASCII中是不连续的。我建议对字母字符使用
[[:alpha:]
,对字母数字使用
[:alnum:]
,但是
[A-Za-z]
[A-Za-z0-9]
没有什么问题。在这两种情况下,您都可能希望允许使用其他字符,例如
\uu
。(这不会立即给你带来任何问题,只是一个提示。)


第三,您拼写的
“implements”
不正确。

对于一般的解析器调试,您可能会发现使用
-DYYDEBUG
编译解析器(java.tab.c
文件)并坚持行
yydebug=1很有用yyparse
之前,先将code>编码到
main
函数中


这将导致解析器打印它读取的所有标记以及执行这些标记时所采取的操作,从而允许您查看它正在执行的操作,并通常显示正在发生的操作以及您认为正确的输入出现意外语法错误的原因。

谢谢,这解决了由于.l文件中缺少默认规则而导致的问题:)