【问题标题】:Yacc/Lexer: how does this work, really?Yacc/Lexer:这是如何工作的,真的吗?
【发布时间】:2012-02-16 10:12:43
【问题描述】:

我曾尝试坐在这里阅读有关 YACC 如何处理 lex 文件的教程,但我不确定我是否能完全理解它。我知道这是为了读取实际的输入文件并确定加法或减法等函数的格式是否正确,但这是如何工作的?我了解 Lex 文件的工作原理,并构建了一个根据文件中遇到的内容返回定义变量的文件。

如果我有一个非常简单的程序,我将如何分析这种测试编程语言的第一行。假设“program”是 lex 中定义的值,以及“is”、“var”、“begin”、“+”、“print”、“;”、“”和“end”。

需要如何编写 yacc 文件才能读取前几行?

测试文件:

program xyz is 
var a, b, c
begin
  a = 2;
  b = 3;
  c = a + b;
  print c
end

Yaccer.y

%token EOFNUM       0
%token SEMINUM      1
%token LPARENNUM    2
%token RPARENNUM    3
%token ICONSTNUM    4
%token BEGINNUM     5
%token PROGRAMNUM   6
%token MINUSNUM     7
%token TIMESNUM     8
%token VARNUM       9
%token COMMANUM     10
%token IDNUM        11
%token ENDNUM       12
%token ISNUM        13
%token PLUSNUM      14
%token DIVNUM       15
%token PRINTNUM     16
%token EQUALNUM     17

%left '+' '-'
%left '*' '/'

%%


%%

#include "lex.yy.c"
#include <stdio.h>

yyerror(str)
char *str;
{   printf("yyerror: %s at line %d\n", str, yyline); }

main () {
    if (!yyparse()) { printf("accept\n");}
    else { printf("reject\n"); }
}

我知道需要为方程式定义一些 %types,但是我不确定如何将这些类型与 %left 声明一起使用,或者即使这是正确的。我也对如何分析第一行感到困惑。

【问题讨论】:

    标签: yacc lex


    【解决方案1】:

    您需要同时创建一个 lex 文件和一个 yacc 文件。在 lex 文件中,您为语法所包含的每种标记定义单独的标记。然后你构建适合 yacc 的 BNF 形式的语法。对于您的简单输入,它看起来有点像这样。我认为print 语句后面没有; 是一个错字,并且该语法需要分号。

    %token IDENTIFIER
    %token PROGRAM
    %token BEGIN
    %token END
    %token IS
    %token VAR
    %token PRINT
    %token NUMBER
    
    program
    statementlist
    statement
    printstatement
    assignstatement 
    expression
    
    %%
    
    program : PROGRAM IDENTIFIER IS VAR variables BEGIN statementlist END;
    
    variables : IDENTIFIER | variables ',' IDENTIFIER;
    
    statementlist : statement | statementlist statement;
    
    statement : assignstatement | printstatement;
    
    printstatement : PRINT IDENTIFIER ';';
    
    assignstatement : IDENTIFIER '=' expression ';';
    
    expression : value | expression '+' value;
    
    value : NUMBER | IDENTIFIER;
    
    %%
    

    %left%right 是关联修饰符,在您的情况下并不真正需要。如果您要使用与+ 相同的优先级来支持-,则需要它们。好吧,从技术上讲并不是真的需要,但它们使语法更容易理解。

    Yacc 不太容易理解,我推荐一个关于这个主题的教程。规则在本质上很快就会变得递归,在使用它时你必须有一定的心态。从最高阶语句开始逐步构建语法更容易。制作一个仅识别程序开始结束的解析器,然后在执行过程中使用这些功能。

    测试和验证语法的好工具是 javascript 解析器生成器 here

    【讨论】:

      猜你喜欢
      • 2011-09-13
      • 2014-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多