将数据从 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()。)