如何将 yytext 从 lex 文件传递​​到 yacc?

发布于 2024-10-09 04:15:28 字数 664 浏览 8 评论 0原文

请我面临一个简单的问题..这就是问题, 在我的 lex 文件中,我有类似的内容:

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 文件中,我有类似的内容:

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 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;
    }

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生死何惧 2024-10-16 04:15:28

修改后的问题

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

我的语法之一包含:

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

#define YYSTYPE Token

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

在语法规则中,您将示例中的 NAME 等项目引用为 $1 (其中实际数量取决于令牌在构成规则的令牌或终端列表中出现的位置)。

例如(相同的语法):

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()同一个文件中的函数。

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;
    }

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

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

原始问题

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

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

哪一个是正确的取决于您的 Lex 版本如何定义它。

如果您想添加长度(可能是 yytextlen),那么您可以定义这样一个变量,并让 yylex() 的每次返回都确保 yytextlen > 已设置。或者,您可以安排您的语法调用 wwlex(),而您的 wwlex() 则简单地执行以下操作:

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

或者您可以安排 Lex 生成带有重命名的代码,并且让 Yacc 继续调用 yylex() 并提供上面的代码作为 yylex() 并让它调用重命名的 Lex 函数。无论哪种方式都有效。

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.

One of my grammars contains:

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

#define YYSTYPE Token

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

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).

For example (same grammar):

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);
        }
    ;

And:

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;
        }
    ;

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;
}

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 */

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

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;
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文