c - Yacc 上下文无关语法

标签 c yacc context-free-grammar

我正在处理类(class)项目。基本上,这是一个 yacc 上下文无关语法项目,我编写了一些代码,但我卡住了并出现语法错误。让我向您展示详细信息:

.l 文件

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

%%

e[0-9]{6}-?[0-9] { 
    return ST; 
}

[-+]?[0-9]+(.[0-9]+)? { return NUMBER; }

[a-z]+ { return ID; }

CNG[0-9][0-9][0-9] { return COURSE; }

ASN[0-9]+ { return ASN; }

\"[^"]*\" { return STR; }

MT[0-9]* { return MT; }

#.* {} /* printf("COMMENT "); */ 

[-+{},:()] { return yytext[0]; } 

[ \t]   { }

\n  { }

.   { printf ("found other data \"%s\"\n", yytext);
    return 1;
}

%%

.y 文件(我编写的)

%{
#include <stdio.h>
#include <string.h>
int yydebug = 0;
%}
%token NUMBER ST STR COURSE ASN MT ID
%%
program: program stmt | stmt;
stmt: func | coursedef | student_info;
coursedef: COURSE ':' '{'st_list '}' { printf("COURSE-DEF\n"); };
st_list: st_list ',' ST | ST;
student_info: ST ':' '{' course_list '}' {printf("STUDENT-INFO\n");};
course_def: COURSE ':' '{' ASN ':' NUMBER ',' MT ':' NUMBER '}';
func: ID '(' param_list ')' { printf("FUNC-CALL\n"); };
param: COURSE | NUMBER | func | STR | ASN | MT | course_add ;
course_add: COURSE "+" COURSE { printf("COURSE-ADD\n"); };

%%

void yyerror(const char *str) { fprintf(stderr,"error: %s\n",str); }

int yywrap() { return 1; } 

int main() { yyparse(); return 0; }

输入:

# define students taking the course
CNG230 : {e8390231, e8390232, e839023-9}

# define grades of students
e8390231 : { CNG230 : { ASN1 :  90.0, MT1 : +100 } } # who writes +100?
e8390232 : { CNG230 : { ASN1 :  30.0, MT1 :   90 } }
e839023-9 : { 
    CNG230 : { ASN1 : 52.6, MT1 : 45.0 },
    CNG492 : { ASN1 : 10.0, MT1 : 20.0 } 
}

# report the average of all grades for CNG230
report(average(CNG230))

# report the curve we get by taking the passing grade down by 30 points
report(curve(CNG230, -30))

# report the average asn 1 grades for CNG230
title("CNG230 ASN1 Average")
report(average(CNG230, ASN1))

# report the average grades over two courses
title("CNG230/492 Global average")
report(average(CNG230 + CNG492))

# report the average grades of students taking
# CNG230 but not taking CNG492
report(average(CNG230 - CNG492))

# report the best student in CNG230
report(best(CNG230, 1)) 

# report the average of grades of the best
# student taking CNG230
report(average(best(CNG230, 1))) # can replace 1 with 3 to get top 3

预期输出:

COURSE-DEF
STUDENT-INFO
STUDENT-INFO
STUDENT-INFO
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
COURSE-ADD
FUNC-CALL
FUNC-CALL
COURSE-SUB
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL
FUNC-CALL

我认为这个项目应该很容易,但我无法从 COURSE-DEF 转移。谁能帮我?

最佳答案

您的规范中遗漏了一些规则/产生式。试试这个:

%{
#include <stdio.h>
#include <string.h>
int yydebug = 0;
%}
%token NUMBER ST STR COURSE ASN MT ID
%%
program         : program stmt
                | stmt
                ;

stmt            : func
                | coursedef
                | student_info
                ;

coursedef       : COURSE ':' '{' st_list '}' { printf("COURSE-DEF\n"); }
                ;

st_list         : st_list ',' ST
                | ST
                ;

student_info    : ST ':' '{' course_list '}' { printf("STUDENT-INFO\n"); }
                ;

course_def      : COURSE ':' '{' ASN ':' NUMBER ',' MT ':' NUMBER '}'
                ;

course_list     : course_list ',' course_def
                | course_def
                ;

func            : ID '(' param_list ')' { printf("FUNC-CALL\n"); }
                ;

param_list      : param_list ',' param
                | param
                ;

param           : COURSE
                | ASN
                | STR
                | MT
                | NUMBER
                | func
                | course_add
                | course_sub
                ;

course_add      : COURSE '+' COURSE { printf("COURSE-ADD\n"); }
                ;

course_sub      : COURSE '-' COURSE { printf("COURSE-SUB\n"); }
                ;

%%

void yyerror(const char *str) { fprintf(stderr,"error: %s\n",str); }

int yywrap() { return 1; } 

int main() { yyparse(); return 0; }

关于c - Yacc 上下文无关语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23619693/

相关文章:

c - 算法编程 Q - 看似正确的解决方案却得到错误的答案

parsing - 编写 BNF 时 { 和 } 之间有什么?

java - 我不知道如何实现递归语法分析器

c++ - 在 C 中,我们可以使用诸如::或 -> 之类的运算符来访问头文件中的预定义方法吗?

c - 将函数指针作为参数传递给 fopen

c - Lex 和 Yacc 段错误

c++ - 使用 flex/yacc 编写 C++ 编译器需要多少时间?

parsing - 如何消除 LL Parser 的左递归

c++ - LBNF、C函数声明/定义、reduce减少冲突

c - 在 C 中动态设置 .data 段大小