【问题标题】:Simple Java grammar using Flex & Bison使用 Flex 和 Bison 的简单 Java 语法
【发布时间】:2013-05-17 03:18:02
【问题描述】:

我最近开始学习基本的 Flex 和 Bison,因为我必须为简单(但不太简单)的语法制作解析器。我决定在我的语法中制作一种简化的 Java 语言。我制作了.l.y 文件,一切编译都没有错误(我正在使用gcc 编译)。 问题是每次我运行生成的程序时都会得到Syntax Error,即使是简单的输入,例如:private class Something{}。唯一一次我没有得到Syntax Error 是当我输入一个空行(\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;
}

【问题讨论】:

    标签: bison flex-lexer


    【解决方案1】:

    这是一个开始:

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

    . { return yytext[0]; }
    

    其次,[A-z][A-Za-z] 不同,因为Za 在ASCII 中不连续。我建议将[[:alpha:]] 用于字母字符,将[[:alnum:]] 用于字母数字,但[A-Za-z][A-Za-z0-9] 没有任何问题。在这两种情况下,您可能都希望允许使用其他字符,例如 _。 (这不会给您带来任何直接的问题,它只是一个注释。)

    第三,你拼错了"implements"

    【讨论】:

    • 谢谢,这解决了我的问题,这是由于 .l 文件中缺少默认规则引起的 :)
    【解决方案2】:

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

    这将导致解析器打印它读取的所有标记和它执行的操作,让您看到它在做什么,通常会显示正在发生的事情以及为什么您认为输入会出现意外的语法错误是正确的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多