【问题标题】:Flex and Yacc Grammar IssueFlex 和 Yacc 语法问题
【发布时间】:2016-08-17 08:41:24
【问题描述】:

编辑 #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() {}

这是我的生成文件:

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

S WHERE CNO = 5

我没有测试所有的东西,但我认为这些问题有一个共同的问题。

【问题讨论】:

    标签: parsing flex-lexer yacc


    【解决方案1】:

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

    S

    后面可以跟 RENAME 或 WHERE 不接受。同样,

    S WHERE CNO = 5

    后面可以跟一个或多个数字,因此 yyparse 在收到 EOF 或意外令牌之前不会接受。

    您想要做的是遵循here 的建议并将 p5.l 更改为具有这些行:

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

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

    另外,您想使用left recursion 表示号码:

    number:
        val
        | number val
        ;
    

    【讨论】:

    • 谢谢,它工作得更好了。不过我有几个问题。什么是 if 语句检查?我不确定yyin == stdin 是什么意思。还有,现在程序一个accept就退出了,如果我想输入更多的命令呢?
    • yyin == stdin 检查输入是否来自标准输入,我们(可能错误地)假设它正在输入。在这种情况下,当用户点击输入时,我们假设它是结束的输入。如果你想接受多行,你应该把yyparse 放在一个循环中。或者你可以要求一个';'在表达式之后,只从文件中读取,或者做一个花哨的repl like this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多