将数据从 flex 传递给 bison 语法
passing data to bison grammar from flex
我的 flex / bison 语法有问题。不确定是不是我设置递归的方式搬起石头砸自己的脚。
当尝试访问通过 yylval 传递的数据时,我会为生产的每个元素使用 $1... 变量。但是,这样做并没有将值拆分为每个标记。它打印整个产品。这只发生在元数据制作中的第二句话,第一句似乎没问题。
我打算创建一个 check(int token_val)
函数,其中包含一个 switch(token_val)
并检查每个标记的 return 值,然后适当地对其 yytext 进行操作。有没有一种方法可以使用 $
变量表示法来为我提供来自命令生产的 return 值?或者这是不正确的处理方式?
我已经检查了这方面的参考资料,但也许我遗漏了什么,希望有人能澄清一下。
代码:野牛
input: input metadata
| metadata
;
metadata: command op data {printf("%s is valid.\n", );} // check_data() ?
| data op data op data op data {printf("row data is valid\n\t %s\n", );}
;
command: PROD_TITL
| _DIR
| DOP
| DIT
| FORMAT
| CAMERA
| CODEC
| DATE
| REEL
| SCENE
| SLATE
;
op: EQUALS
| COLON
| SEP
;
data: META
| REEL_ID
| SCENE_ID
| SLATE_ID
| TAKE
| MULTI_T
| LENS
| STOP
| FILTERS
;
%%
int main(void) {
return yyparse();
}
莱克斯:
%{
#include <stdio.h>
#include <string.h>
#include "ca_mu.tab.h"
%}
%option yylineno
%%
\"[^"\n]*["\n] {yylval = yytext; return META;}
[aA-aZ][0-9]+ {yylval = yytext; return REEL_ID;}
([0-9aA-zZ]*\/[0-9aA-zZ]*) {yylval = yytext; return SCENE_ID;}
[0-9]+ {yylval = yytext; return SLATE_ID;}
[0-9][aA-zZ]+ {yylval = yytext; return TAKE;}
[0-9]+-[0-9]+ {yylval = yytext; return MULTI_T;}
[0-9]+MM {yylval = yytext; return LENS;}
T[0-9]\.[0-9]+ {yylval = yytext; return STOP;}
"{"([^}]*)"}" {yylval = yytext; return FILTERS;}
输出样本:
"My Production" is valid.
"Dir Name" is valid.
"DOP Name" is valid.
"DIT Name" is valid.
"16:9" is valid.
"Arri Alexa" is valid.
"ProRes" is valid.
"02/12/2020" is valid.
A001 is valid.
23/22a is valid.
001 is valid.
row data is valid
1, 50MM, T1.8, { ND.3 } // prints all tokens?
row data is valid
3AFS, 50MM, T1.8, {ND.3}
输入
/* This is a comment */
production_title = "My Production"
director = "Dir Name"
DOP = "DOP Name"
DIT = "DIT Name"
format = "16:9"
camera = "Arri Alexa"
codec = "ProRes"
date = "02/12/2020"
reel: A001
scene: 23/22a
slate: 001
1, 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}
END
我觉得你的语言太简单了,没有定义输入的结构。例如:
reel: A001 // repetition of reels, consisting of....
scene: 23/22a // repetition of scenes, consisting of...
slate: 001 // repetition of slates, consisting of...
1, 50MM, T1.8, { ND.3 } // repetition of slate data
这是一个结构体,所以输入是:
movie: metadata reels
;
metadata: /* see your stuff */ ;
reels: reel
| reels reel
;
reel: REEL REEL_ID scenes
;
scenes: scene
| scenes scene
;
scene: SCENE SCENE_ID slates
;
slates: slate
| slates slate
;
slate: SLATE SLATE_ID slate_datas
;
slate_datas: slate_data
| slate_datas slate_data
;
slate_data: /*your stuff*/ ;
问题出在这里,在您的扫描仪操作中:
yylval = yytext;
你绝不能这样做。
yytext
指向临时缓冲区,该缓冲区仅在下一次调用 yylex()
之前有效,这意味着您有效地使 yylval
成为悬空指针。始终复制字符串,如:
yylval = strdup(yytext);
(当您不再需要副本时,不要忘记对复制的字符串调用 free()
。)
我的 flex / bison 语法有问题。不确定是不是我设置递归的方式搬起石头砸自己的脚。
当尝试访问通过 yylval 传递的数据时,我会为生产的每个元素使用 $1... 变量。但是,这样做并没有将值拆分为每个标记。它打印整个产品。这只发生在元数据制作中的第二句话,第一句似乎没问题。
我打算创建一个 check(int token_val)
函数,其中包含一个 switch(token_val)
并检查每个标记的 return 值,然后适当地对其 yytext 进行操作。有没有一种方法可以使用 $
变量表示法来为我提供来自命令生产的 return 值?或者这是不正确的处理方式?
我已经检查了这方面的参考资料,但也许我遗漏了什么,希望有人能澄清一下。
代码:野牛
input: input metadata
| metadata
;
metadata: command op data {printf("%s is valid.\n", );} // check_data() ?
| data op data op data op data {printf("row data is valid\n\t %s\n", );}
;
command: PROD_TITL
| _DIR
| DOP
| DIT
| FORMAT
| CAMERA
| CODEC
| DATE
| REEL
| SCENE
| SLATE
;
op: EQUALS
| COLON
| SEP
;
data: META
| REEL_ID
| SCENE_ID
| SLATE_ID
| TAKE
| MULTI_T
| LENS
| STOP
| FILTERS
;
%%
int main(void) {
return yyparse();
}
莱克斯:
%{
#include <stdio.h>
#include <string.h>
#include "ca_mu.tab.h"
%}
%option yylineno
%%
\"[^"\n]*["\n] {yylval = yytext; return META;}
[aA-aZ][0-9]+ {yylval = yytext; return REEL_ID;}
([0-9aA-zZ]*\/[0-9aA-zZ]*) {yylval = yytext; return SCENE_ID;}
[0-9]+ {yylval = yytext; return SLATE_ID;}
[0-9][aA-zZ]+ {yylval = yytext; return TAKE;}
[0-9]+-[0-9]+ {yylval = yytext; return MULTI_T;}
[0-9]+MM {yylval = yytext; return LENS;}
T[0-9]\.[0-9]+ {yylval = yytext; return STOP;}
"{"([^}]*)"}" {yylval = yytext; return FILTERS;}
输出样本:
"My Production" is valid.
"Dir Name" is valid.
"DOP Name" is valid.
"DIT Name" is valid.
"16:9" is valid.
"Arri Alexa" is valid.
"ProRes" is valid.
"02/12/2020" is valid.
A001 is valid.
23/22a is valid.
001 is valid.
row data is valid
1, 50MM, T1.8, { ND.3 } // prints all tokens?
row data is valid
3AFS, 50MM, T1.8, {ND.3}
输入
/* This is a comment */
production_title = "My Production"
director = "Dir Name"
DOP = "DOP Name"
DIT = "DIT Name"
format = "16:9"
camera = "Arri Alexa"
codec = "ProRes"
date = "02/12/2020"
reel: A001
scene: 23/22a
slate: 001
1, 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}
END
我觉得你的语言太简单了,没有定义输入的结构。例如:
reel: A001 // repetition of reels, consisting of....
scene: 23/22a // repetition of scenes, consisting of...
slate: 001 // repetition of slates, consisting of...
1, 50MM, T1.8, { ND.3 } // repetition of slate data
这是一个结构体,所以输入是:
movie: metadata reels
;
metadata: /* see your stuff */ ;
reels: reel
| reels reel
;
reel: REEL REEL_ID scenes
;
scenes: scene
| scenes scene
;
scene: SCENE SCENE_ID slates
;
slates: slate
| slates slate
;
slate: SLATE SLATE_ID slate_datas
;
slate_datas: slate_data
| slate_datas slate_data
;
slate_data: /*your stuff*/ ;
问题出在这里,在您的扫描仪操作中:
yylval = yytext;
你绝不能这样做。
yytext
指向临时缓冲区,该缓冲区仅在下一次调用 yylex()
之前有效,这意味着您有效地使 yylval
成为悬空指针。始终复制字符串,如:
yylval = strdup(yytext);
(当您不再需要副本时,不要忘记对复制的字符串调用 free()
。)