如何将yytext从lex文件传递到yacc? [英] How to pass the yytext from the lex file to 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屋!