如何将yytext从lex文件传递到yacc? [英] How to pass the yytext from the lex file to yacc?

查看:110
本文介绍了如何将yytext从lex文件传递到yacc?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请我遇到一个简单的问题..这是问题, 在我的lex文件中,我有类似的东西:

Please i am facing a simple problem.. here is the issue, In my lex file i have something similiar to:

char *ptr_String;

"name = "  { BEGIN sName; }

<sName>.+   {
          ptr_String = (char *)calloc(strlen(yytext)+1, sizeof(char));
              strcpy(ptr_String, yytext);
              yylval.sValue = ptr_String;
              return NAME;
    }

现在在我的Yacc文件中,我有类似的内容:

Now in my Yacc file i have something similar to:

stmt_Name:
    NAME
    {
        /*Now here i need to get the matched string of <sName>.+ and measure it's length. */
        /*The aim is simply outputing the name to the screen and storing the length in a global variable.
    }
    ;

有什么建议吗? 非常感谢您的所有时间和帮助.

Please any suggestions? Thanks so much for all your time and help.

推荐答案

修订后的问题

Yacc堆栈上的值由YYSTYPE或%union控制.当类型信息很简单时,请使用YYSTYPE;复杂时使用%union.

Revised question

The value on the Yacc stack is controlled by YYSTYPE or %union. Use YYSTYPE when the type information is simple; use %union when it is complex.

我的一个语法包含:

struct Token
{
    int      toktype;
    char    *start;
    char    *end;
};
typedef struct Token Token;

#define YYSTYPE Token

出于各种原因(不一定是好的原因),我的语法使用了手工制作的词法分析器,而不是Lex.

For a variety of reasons (not necessarily good ones), my grammar uses a hand-crafted lexical analyzer instead of Lex.

在语法规则中,您在示例中将诸如NAME之类的内容称为$1(其中实际数字取决于令牌在组成规则的令牌或终端列表中的位置).

In the grammar rules, you refer to items like NAME in your example as $1 (where the actual number depends on where the token appears in the list of tokens or terminals that make up the rule).

例如(相同的语法):

disconnect
    :   K_DISCONNECT K_CURRENT
        { conn->ctype = CONN_CURRENT; }
    |   K_DISCONNECT K_ALL
        { conn->ctype = CONN_ALL; }
    |   K_DISCONNECT K_DEFAULT
        { conn->ctype = CONN_DEFAULT; }
    |   K_DISCONNECT string
        { conn->ctype = CONN_STRING;
          set_connection(conn, $2.start, $2.end);
        }
    ;

并且:

load
    :   K_LOAD K_FROM opt_file_pipe string load_opt_list K_INSERT
        {
            set_string("load file", load->file, sizeof(load->file),
                       $4.start, $4.end);
            load->stmt = $6.start;
        }
    ;

我不知道看到手工制作的yylex()的轮廓是否有帮助;在语法上,它是与yyparse()在同一文件中的函数.

I don't know whether seeing the outline of the hand-crafted yylex() helps; in the grammar, it is a function in the same file as yyparse().

static const char *c_token;     /* Where to start next token search */

static int yylex(void)
{
    char        buffer[MAX_LEXTOKENLENGTH];
    const char *start;

    if (c_token == 0)
        abort();

    if (bare_filename_ok)
        start = scan_for_filename(c_token, &c_token);
    else
        start = sqltoken(c_token, &c_token);

    yylval.start = CONST_CAST(char *, start);
    yylval.end = CONST_CAST(char *, c_token);
    if (*start == '\0')
    {
        yylval.toktype = 0;
        return yylval.toktype;
    }
    set_token(buffer, sizeof(buffer), start, c_token);
#ifdef YYDEBUG
    if (YYDEBUGVAR > 1)
        printf("yylex(): token = %s\n", buffer);
#endif /* YYDEBUG */

    /* printf("yylex(): token = %s\n", buffer); */
    if (isalpha((unsigned char)buffer[0]) || buffer[0] == '_')
    {
        Keyword  kw;
        Keyword *p;
        kw.keyword = buffer;
        p = (Keyword *)bsearch(&kw, keylist, DIM(keylist), sizeof(Keyword),
                                kw_compare);    /*=C++=*/
        if (p == 0)
            yylval.toktype = S_IDENTIFIER;
        else
            yylval.toktype = p->token;
    }
    else if (buffer[0] == '\'')
    {
        yylval.toktype = S_SQSTRING;
    }
    else if (buffer[0] == '"')
    {
        yylval.toktype = S_DQSTRING;
    }
    else if (isdigit((unsigned char)buffer[0]))
    {
        yylval.toktype = S_NUMBER;
    }
    else if (buffer[0] == '.' && isdigit((unsigned char)buffer[1]))
    {
        yylval.toktype = S_NUMBER;
    }

...识别出各种单字符符号...

...various single-character symbols recognized...

    else if (buffer[0] == ':')
    {
        assert(buffer[1] == '\0');
        yylval.toktype = C_COLON;
    }
    else
    {
        yylval.toktype = S_ERROR;
    }
    return yylval.toktype;
}

原始问题

该变量通常是全局变量-您的Yacc代码使用两种可能的声明之一:

Original question

The variable is normally a global variable - your Yacc code uses one of two possible declarations:

extern char *yytext;    /* Correct for Flex */
extern char yytext[];   /* Correct for traditional Lex */

其中哪些是正确的,取决于您的Lex版本如何定义它.

Which of those is correct depends on how your version of Lex defines it.

如果要添加长度(也许是yytextlen),则可以定义这样的变量,并使yylex()的每个返回值都确保已设置yytextlen.另外,您可以安排语法调用wwlex(),而wwlex()只需执行以下操作:

If you want to add a length (perhaps yytextlen), then you can define such a variable and have every return from yylex() ensure that yytextlen is set. Alternatively, you can arrange for your grammar to call wwlex(), and your wwlex() simply does:

int wwlex(void)
{
    int rc = yylex();
    yytextlen = strlen(yytext);
    return rc;
}

或者您可以安排Lex使用重命名生成代码,并让Yacc继续调用yylex(),您将上面的代码提供为yylex(),并让其调用重命名的Lex函数.不管哪种方法.

Or you can arrange for Lex to generate code with the rename, and have Yacc continue to call yylex() and you provide the code above as yylex() and have it call the renamed Lex function. Either way works.

这篇关于如何将yytext从lex文件传递到yacc?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆