繁体   English   中英

Flex和Yacc语法问题

[英]Flex and Yacc Grammar Issue

编辑#1:我认为问题出在我的.l文件中。 我不认为规则被视为规则,并且我不确定如何将规则的终端视为字符串。

对于编译器类,我的最后一个项目是为简单的SQL语法编写.l和.y文件。 我没有使用Flex或Yacc的经验,所以我编写的所有内容都是拼凑而成的。 我对这些文件的工作方式只有一个基本的了解,因此,如果发现我的问题,还可以解释文件的那一部分应该做什么吗? 我什至不知道'%'符号的作用。

基本上,某些规则在我尝试解析某些内容时不起作用。 一些规则挂起,而其他规则则应接受时拒绝。 我需要实现以下语法:

start 
    ::= expression

expression
    ::= one-relation-expression | two-relation-expression

one-relation-expression
    ::= renaming | restriction | projection

renaming 
    ::= term RENAME attribute AS attribute

term 
    ::= relation | ( expression )

restriction
    ::= term WHERE comparison

projection 
    ::= term | term [ attribute-commalist ]

attribute-commalist
    ::= attribute | attribute , attribute-commalist

two-relation-expression
    ::= projection binary-operation expression

binary-operation
    ::= UNION | INTERSECT | MINUS | TIMES | JOIN | DIVIDEBY

comparison
    ::= attribute compare number

compare
    ::= < | > | <= | >= | = | <>

number
    ::= val | val number

val 
    ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

attribute 
    ::= CNO | CITY | CNAME | SNO | PNO | TQTY | 
          SNAME | QUOTA | PNAME | COST | AVQTY |
          S# | STATUS | P# | COLOR | WEIGHT | QTY

relation 
    ::= S | P | SP | PRDCT | CUST | ORDERS

这是我的.l文件:

%{
#include <stdio.h>
#include "p5.tab.h"
%}
binaryOperation     UINION|INTERSECT|MINUS|TIMES|JOIN|DIVIDEBY
compare         <|>|<=|>=|=|<>
attribute       CNO|CITY|CNAME|SNO|PNO|TQTY|SNAME|QUOTA|PNAME|COST|AVQTY|S#|STATUS|P#|COLOR|WEIGHT|QTY
relation        S|P|SP|PRDCT|CUST|ORDERS
%%
[ \t\n]+        ;
{binaryOperation}   return binaryOperation;
{compare}       return compare;
[0-9]+          return val;
{attribute}     return attribute;
{relation}      return relation;
"RENAME"        return RENAME;
"AS"            return AS;
"WHERE"         return WHERE;
"("         return '(';
")"         return ')';
"["         return '[';
"]"         return ']';
","         return ',';
.           {printf("REJECT\n");
                exit(0);}
%%

这是我的.y文件:

%{
#include <stdio.h>
#include <stdlib.h>
%}
%token RENAME attribute AS relation WHERE binaryOperation compare val
%%

start:
    expression          {printf("ACCEPT\n");}
    ;

expression:
    oneRelationExpression
    | twoRelationExpression
    ;

oneRelationExpression:
    renaming
    | restriction
    | projection
    ;

renaming:
    term RENAME attribute AS attribute
    ;

term:
    relation
    | '(' expression ')'
    ;

restriction:
    term WHERE comparison
    ;

projection:
    term
    | term '[' attributeCommalist ']'
    ;

attributeCommalist:
    attribute
    | attribute ',' attributeCommalist
    ;

twoRelationExpression:
    projection binaryOperation expression
    ;

comparison:
    attribute compare number
    ;

number:
    val
    | val number
    ;

%%

yyerror() {
    printf("REJECT\n");
    exit(0);
}

main() {
    yyparse();
}

yywrap() {}

这是我的makefile:

p5: p5.tab.c lex.yy.c
    cc -o p5 p5.tab.c lex.yy.c

p5.tab.c: p5.y
    bison -d p5.y

lex.yy.c: p5.l
    flex p5.l

这有效:

重命名CNO为城市

这些不:

小号

S CNO = 5

我尚未测试所有内容,但我认为这些问题存在一个普遍的问题。

您的语法是正确的,问题是您正在交互式运行。 当您调用yyparse()时,它将尝试读取所有输入。 因为输入

小号

后面可能跟有RENAME或WHERE,它将不被接受。 同样,

S CNO = 5

可能后跟一个或多个数字,因此yyparse不会接受,直到获得EOF或意外的令牌。

您要做的是按照此处的建议进行操作并将p5.l更改为以下行:

[ \t]+        ;
\n            if (yyin==stdin) return 0;

这样,当您以交互方式运行时,它将以ENTER键作为输入的结尾。

另外,您想对数字使用左递归

number:
    val
    | number val
    ;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM