yacc 定义的结构
stucture of yacc definitions
我正在为个人项目的标记语言编写解析器:
样本:
/* This is a comment */
production_title = "My Production"
director = "Joe Smith"
DOP = "John Blogs"
DIT = "Random Name"
format = "16:9"
camera = "Arri Alexa"
codec = "ProRes"
date = _auto
Reel: A001
Scene: 23/22a
Slate: 001
1-2, 50MM, T1.8, {ND.3}
3AFS, 50MM, T1.8, {ND.3}
Slate: 002:
1, 65MM, T1.8, {ND.3 BPM1/2}
Slate: 003:
1-3, 24MM, T1.9 {ND.3}
Reel: A002
Scene: 23/22a
Slate: 004
1-5, 32MM, T1.9, {ND.3}
Scene: 23/21
Slate: 005
1, 100MM, T1.9, {ND.6}
END
我已经开始学习 lex 和 yacc,并且已经 运行 解决了一些关于语法定义结构的问题。
yacc.y
%{
#include <stdio.h>
int yylex();
void yyerror(char *s);
%}
%token PROD_TITL _DIR DOP DIT FORMAT CAMERA CODEC DATE EQUALS
%right META
%%
meta: PROD_TITL EQUALS META {
printf("%s is set to %s\n",, );
}
| _DIR EQUALS META {
printf("%s is set to %s\n",, );
}
%%
int main(void) {
return yyparse();
}
void yyerror(char *s) {fprintf(stderr, "%s\n", s);}
lex.l
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
"production_title" {yylval = strdup(yytext); return PROD_TITL;}
"director" {yylval = strdup(yytext); return _DIR;}
"DOP" return DOP;
"DIT" return DIT;
"format" return FORMAT;
"camera" return CAMERA;
"codec" return CODEC;
"date" return DATE;
"exit" exit(EXIT_SUCCESS);
\"[^"\n]*["\n] { yylval = strdup(yytext);
return META;
}
= return EQUALS;
[ \t\n] ;
"/*"([^*]|\*+[^*/])*\*+"/" ;
. printf("unrecognized input\n");
%%
int yywrap(void) {
return 1;
}
我遇到的主要问题是该程序仅 运行 在第一次解析时正确,然后它 returns 是一个不正确的语法错误。这和我写语法的方式有关吗?
来自 sample.txt 并输入命令的示例输出:
hc@linuxtower:~/Documents/CODE/parse> ./a.out < sample.txt
production_title is set to "My Production"
syntax error
hc@linuxtower:~/Documents/CODE/parse> ./a.out
production_title = "My Production"
production_title is set to "My Production"
director = "Joe Smith"
syntax error
编译时,我在 lex.l 文件中收到关于我的正则表达式的警告:
ca_mu.l: In function ‘yylex’:
ca_mu.l:9:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
"production_title" {yylval = strdup(yytext); return PROD_TITL;}
^
ca_mu.l:10:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
"director" {yylval = strdup(yytext); return _DIR;}
^
ca_mu.l:20:10: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
\"[^"\n]*["\n] { yylval = strdup(yytext);
^
这可能是问题的根源还是其他问题?
这是两个不同的问题。
你的语法如下,省略了动作:
meta: PROD_TITL EQUALS META
| _DIR EQUALS META
这意味着您的语法接受两个序列之一,它们都恰好具有三个标记。也就是说,它接受 "PROD_TITL EQUALS META" 或“_DIR EQUALS META”。而已。一旦找到其中之一,它就会尽可能多地进行解析,并期望被告知输入已完成。任何其他输入都是错误的。
编译器抱怨 yylval = strdup(yytext);
因为它被告知 yylval
是 int
类型。那是 yacc/bison 的默认语义类型;如果你不做任何改变它,这就是 bison 会假设的,它会在它生成的头文件中插入 extern int yylval;
,这样词法分析器就知道语义类型是什么。如果您在互联网上搜索,您可能会发现各种宏黑客建议来更改此设置,但使用 "modern" bison 的正确方法是在您的 bison 文件中插入以下声明,在序言的某处:
%declare api.value.type { char* }
稍后,您可能会发现您需要联合类型而不是将所有内容都设为字符串。在达到这一点之前,您应该阅读 Bison 手册中关于 Defining Semantic Values 的部分。 (事实上 ,建议您从头到尾阅读 Bison 手册,包括第 2 节中的简单示例。它不长,而且非常容易阅读。)
我正在为个人项目的标记语言编写解析器:
样本:
/* This is a comment */
production_title = "My Production"
director = "Joe Smith"
DOP = "John Blogs"
DIT = "Random Name"
format = "16:9"
camera = "Arri Alexa"
codec = "ProRes"
date = _auto
Reel: A001
Scene: 23/22a
Slate: 001
1-2, 50MM, T1.8, {ND.3}
3AFS, 50MM, T1.8, {ND.3}
Slate: 002:
1, 65MM, T1.8, {ND.3 BPM1/2}
Slate: 003:
1-3, 24MM, T1.9 {ND.3}
Reel: A002
Scene: 23/22a
Slate: 004
1-5, 32MM, T1.9, {ND.3}
Scene: 23/21
Slate: 005
1, 100MM, T1.9, {ND.6}
END
我已经开始学习 lex 和 yacc,并且已经 运行 解决了一些关于语法定义结构的问题。
yacc.y
%{
#include <stdio.h>
int yylex();
void yyerror(char *s);
%}
%token PROD_TITL _DIR DOP DIT FORMAT CAMERA CODEC DATE EQUALS
%right META
%%
meta: PROD_TITL EQUALS META {
printf("%s is set to %s\n",, );
}
| _DIR EQUALS META {
printf("%s is set to %s\n",, );
}
%%
int main(void) {
return yyparse();
}
void yyerror(char *s) {fprintf(stderr, "%s\n", s);}
lex.l
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
"production_title" {yylval = strdup(yytext); return PROD_TITL;}
"director" {yylval = strdup(yytext); return _DIR;}
"DOP" return DOP;
"DIT" return DIT;
"format" return FORMAT;
"camera" return CAMERA;
"codec" return CODEC;
"date" return DATE;
"exit" exit(EXIT_SUCCESS);
\"[^"\n]*["\n] { yylval = strdup(yytext);
return META;
}
= return EQUALS;
[ \t\n] ;
"/*"([^*]|\*+[^*/])*\*+"/" ;
. printf("unrecognized input\n");
%%
int yywrap(void) {
return 1;
}
我遇到的主要问题是该程序仅 运行 在第一次解析时正确,然后它 returns 是一个不正确的语法错误。这和我写语法的方式有关吗?
来自 sample.txt 并输入命令的示例输出:
hc@linuxtower:~/Documents/CODE/parse> ./a.out < sample.txt
production_title is set to "My Production"
syntax error
hc@linuxtower:~/Documents/CODE/parse> ./a.out
production_title = "My Production"
production_title is set to "My Production"
director = "Joe Smith"
syntax error
编译时,我在 lex.l 文件中收到关于我的正则表达式的警告:
ca_mu.l: In function ‘yylex’:
ca_mu.l:9:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
"production_title" {yylval = strdup(yytext); return PROD_TITL;}
^
ca_mu.l:10:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
"director" {yylval = strdup(yytext); return _DIR;}
^
ca_mu.l:20:10: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
\"[^"\n]*["\n] { yylval = strdup(yytext);
^
这可能是问题的根源还是其他问题?
这是两个不同的问题。
你的语法如下,省略了动作:
meta: PROD_TITL EQUALS META | _DIR EQUALS META
这意味着您的语法接受两个序列之一,它们都恰好具有三个标记。也就是说,它接受 "PROD_TITL EQUALS META" 或“_DIR EQUALS META”。而已。一旦找到其中之一,它就会尽可能多地进行解析,并期望被告知输入已完成。任何其他输入都是错误的。
编译器抱怨
yylval = strdup(yytext);
因为它被告知yylval
是int
类型。那是 yacc/bison 的默认语义类型;如果你不做任何改变它,这就是 bison 会假设的,它会在它生成的头文件中插入extern int yylval;
,这样词法分析器就知道语义类型是什么。如果您在互联网上搜索,您可能会发现各种宏黑客建议来更改此设置,但使用 "modern" bison 的正确方法是在您的 bison 文件中插入以下声明,在序言的某处:%declare api.value.type { char* }
稍后,您可能会发现您需要联合类型而不是将所有内容都设为字符串。在达到这一点之前,您应该阅读 Bison 手册中关于 Defining Semantic Values 的部分。 (事实上 ,建议您从头到尾阅读 Bison 手册,包括第 2 节中的简单示例。它不长,而且非常容易阅读。)