首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >yacc输出帮助

yacc输出帮助
EN

Stack Overflow用户
提问于 2011-02-16 16:14:21
回答 2查看 841关注 0票数 0

如果我有这个语法

start : TKN id '{' '}' {cout<<$2<<endl;} ;

包含

  • iostream,TKN被声明为令牌,id类型声明为char *
  • 作为输入i进入

输出不应该是aaa吗??有时,它打印}0,有时只是挂起

我想要得到id的价值,如何得到它的正确??

lex.l

代码语言:javascript
复制
%{
  #include "yacc.hpp"
  #include <math.h>
  #include<iostream>
  #include<string>
  int rows = 1,tmp=0;
%}
Id          [a-zA-Z_][0-9a-zA-Z_]*
%x String ...
%option c++
%option noyywrap
%% 
{Id}        {strcpy(yylval.strVal,yytext);cout<<"lex= "<<yytext<<endl;return Id;}//output line 1
...

yacc.y

代码语言:javascript
复制
%output ="yacc.cpp"
%defines
%verbose
%token Id
%token NAMESPACE
%union{

int           iVal;
float         fVal;
char*         strVal;
class Symbol* symPtr;
class NS*     nsPtr;
};


%token <iVal> INT_VAL;
%token <fVal> F_VAL;
%token <strVal> STR_VAL INT FLOAT STRING Id ;
%type <nsPtr> namespacedecl  
%type <symPtr> ns_closer
%type <strVal> Q_ID

//-------------------------------------------
namespacedecl  : NAMESPACE Q_ID '{' '}'            {cout<<"ns= "<<$2<< endl ;} // output line 3
               | NAMESPACE Q_ID '{' typedecl_closer '}' ;

 Q_ID :          Q_ID '.' Id                       {cout<<$3<< endl ;$$ = $3;}
               | Id                                {$$ = $1;cout<<"qid="<<$$<<endl;} // output line 2

当然,文件比这个大,但是复制/粘贴任何东西都会让你迷失^^。

如果有附加文件的方法,请告诉我,因为我还是这里的新手,这比复制/粘贴要容易得多。

这就是我跑步时得到的东西:

谢谢你的回复

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-16 22:52:58

这在很大程度上取决于您的id令牌作为yylval返回的内容,因为这是在标记移动时复制到解析器堆栈的内容,因此,在计算规则时,$2引用了什么。据猜测,您有一个lex规则,类似于:

代码语言:javascript
复制
[a-zA-Z_][a-zA-Z_0-9]*      { yylval.str = yytext; return id; }

使用

代码语言:javascript
复制
%token<str>    id

在你的解析器里。在本例中,您正在将指针存储到flex的内部扫描器缓冲区中,该缓冲区在瞬间包含“aaa”,但将被稍后的令牌覆盖,因此在操作运行时,指针以$2的形式指向其他内容。您需要将字符串复制到不会被覆盖的位置,并将yylval设置为指向该字符串。您可以使用strdup(3)将字符串复制到一个错误的缓冲区,这将解决这个问题,但可能会给您留下内存泄漏。

编辑

有了你的附加信息,你的程序没有崩溃是很令人惊讶的--你把标记文本strcpyyylval.strVal,但是你从来没有初始化yylval.Strval来指向任何地方,所以你把它复制到一些随机的内存位置。您需要将类似于yylval.strVal = malloc(strlen(yytext)+1);的内容添加到lev.l操作中,以确保它指向有效内存,或者只需使用更简单和等效的调用来实现支持,因为这结合了malloc和strcpy:

代码语言:javascript
复制
[a-zA-Z_][a-zA-Z_0-9]*      { yylval.str = strdup(yytext); return id; }
票数 0
EN

Stack Overflow用户

发布于 2011-02-17 00:06:24

这取决于“id”规则返回了什么!

代码语言:javascript
复制
%%
start :             TKN id '{' '}' {cout<<$2<<endl;} ;

id :                ID             { return "XXXXX"; } // What is returned here
                                                       // Is what will be printed out by $2 

%%

注意:

按照惯例,终端令牌是全大写(TKN).而非终端令牌是小写(id)。根据这个约定,我希望id有一个关于如何扩展它的规则。

我怀疑你在做的是:

代码语言:javascript
复制
%%

id :                ID             { return yytext; }

%%

这是一个指向lex缓冲区的指针。这是一个易失性的缓冲区。您可以而不是依赖于它的内容保持不变(也不能依赖它被'\0‘终止)。您需要做的是在标识令牌时复制它。

代码语言:javascript
复制
%%

id :                ID             { return strndup(yytext, yylen); }

%%

根据新输入编辑:

在以下几行:

代码语言:javascript
复制
{Id}        {   strcpy(yylval.strVal,yytext);
                cout<<"lex= "<<yytext<<endl;
                return Id;
            }

strcpy()可能是坏的。

  • 您是否为该副本预留了空间?
  • 您不能依赖yytext被“0”终止。

cout是危险的,因为您不能依赖yytext被“\0”终止。

我会这样做:

代码语言:javascript
复制
{ID}        {   cout << "lex=" << std::string(yytext,yytext+yylen); // use yylen
                return Id;
            }

不要在lex中乱搞yacc结构。它将您的lex文件紧密耦合到yacc (这不是必要的)。把记号还回去。然后,yacc可以手动获取令牌值。

然后在YACC文件中:

代码语言:javascript
复制
Q_ID :        Q_ID '.' ident        {$$ = $3; cout<<"Q.id="<<$$<<endl;}
           |  ident                 {$$ = $1; cout<<"ID  ="<<$$<<endl;}

ident :       Id                    {$$ = strndup(yytext, yylen);}

对于每一个具有长令牌的终端(Id),都有一个用于对终端进行去编码的非终端,并在yacc联合结构中生成正确的值。在这种情况下,我们有身份,而不是终端。它只是解码Id终端并获得正确设置的令牌(此Id在联合结构中没有类型)。

另请注意:

  • 终端机是传统的全封顶。Id失败.
  • --非终端采用小写是传统的.Q_ID失败。

此外:

这一行:

代码语言:javascript
复制
%token <strVal> STR_VAL INT FLOAT STRING Id ;

看上去不对,尽管不知道INT、FLOAT和STRING是什么是很难分辨的。我猜这些都是关键字int、float、string的终端令牌。在这种情况下,不需要存储实际的令牌字符串。知道它是INT/FLOAT或STRING这一事实就足够了。

这应该是:

代码语言:javascript
复制
%token <strVal> STR_VAL;
%token <strVal> ident;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5018931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档