我想解析我在 yacc 的主函数中提供给解析器的字符串。我知道这可以通过使用来完成,yy_scan_string
但我不知道如何使用它。我搜索了网页和手册页,但我仍然不清楚。请帮我。
问问题
14667 次
6 回答
19
如果有人需要可重入词法分析器的样本:
int main(void)
{
yyscan_t scanner;
YY_BUFFER_STATE buf;
yylex_init(&scanner);
buf = yy_scan_string("replace me with the string youd like to scan", scanner);
yylex(scanner);
yy_delete_buffer(buf, scanner);
yylex_destroy(scanner);
return 0;
}
于 2011-06-14T21:23:04.253 回答
9
这对我有用。我在 Bison 文件的子程序部分(即第三部分)中有这段代码:
struct eq_tree_node *parse_equation(char *str_input)
{
struct eq_tree_node *result;
yy_scan_string(str_input);
yyparse();
/* to avoid leakage */
yylex_destroy();
/* disregard this. it is the function that I defined to get
the result of the parsing. */
result = symtab_get_parse_result();
return result;
}
于 2010-09-01T13:50:19.017 回答
4
这对我有用......使用 yy_scan_string()
int main(int argc, char **argv)
{
char Command[509];
int ReturnVal;
char input[40] = "This is my input string";
/*Copy string into new buffer and Switch buffers*/
yy_scan_string (input);
/*Analyze the string*/
yylex();
/*Delete the new buffer*/
yy_delete_buffer(YY_CURRENT_BUFFER);
}
于 2012-03-29T07:00:34.200 回答
3
我总是向想学习 lex/yacc(或 flex/bison)的人推荐这个页面
于 2009-12-15T14:37:56.683 回答
0
这里已经有一些很好的答案。但出于我的目的,我需要在要分析的字符串缓冲区之间反复交换。这里的问题是 flex 需要在每次处理运行后进行清理,并重置其内部 parse-stuff/counters/etc。 在撰写本文时,现有的答案都没有证明这一点。
从本质上讲,这相当于在某个地方保留 a ,并在需要在字符串之间切换时YY_BUFFER_STATE yy_buffer_state;
调用。yy_delete_buffer( yy_buffer_state )
当 flex 被分配一个新的字符串来扫描( with yy_scan_string()
)时,会生成一个新的 YY_BUFFER_STATE,您需要对其进行跟踪。
我试图展示一个相当完整的例子,但金钱射击 setLexerBuffer()
接近底部~
例如:
%{
#include "flex_tokens_and_yylval.h"
extern LexYYLVal yylval; // my custom yylval
extern YY_BUFFER_STATE yy_buffer_state;
%}
digit [0-9]
letter [a-zA-Z]
udderscore "_"
sign [+-]
period "."
real {sign}?({digit}*{period}{digit}+)
int {sign}?{digit}+
identifier ({letter}|{udderscore})+({letter}|{digit}|{udderscore})*
/* [...] rest of the scanner rules */
%%
<<EOF>> { return LEX_EOF; }
{real} {
yylval.data.val_real = strtod( yytext, NULL );
return LEX_REAL;
}
{int} {
yylval.data.val_integer = strtol( yytext, NULL, 10 );
return LEX_INTEGER;
}
{identifier} {
strncpy( yylval.data.val_string, yytext, MAX_IDENTIFIER_LENGTH );
yylval.data.val_string[MAX_IDENTIFIER_LENGTH-1]='\0';
return LEX_IDENTIFIER;
}
[ \t\n\r] { /* skip whitespace */ }
/* [...] rest the scanner outputs */
%%
// NOT THREAD SAFE, DON'T USE FROM MULTIPLE THREADS
LexYYLVal yylval;
int yy_first_ever_run = 1;
char LexEmptyBuffer[3] = { '\n', '\0', '\0' };
YY_BUFFER_STATE yy_buffer_state;
/*
* Point flex at a new string to process, resetting
* any old results from a previous parse.
*/
void setLexerBuffer( const char *expression_string )
{
/* out with the old (If any? How does flex know?) */
if ( !yy_first_ever_run )
{
// This doesn't cause any issues (according to valgrind)
// but I also don't see any reason to call it before the
// first lex-run.
yy_delete_buffer( yy_buffer_state );
}
else
{
yy_first_ever_run = 0;
}
/* just make sure we're pointing at something */
if ( expression_string == NULL )
{
expression_string = LexEmptyBuffer;
}
/* reset the scan */
yy_buffer_state = yy_scan_string( expression_string ); /* auto-resets lexer state */
}
所以这可以让你运行一个控制循环,比如:
int main( void )
{
LexResultToken token;
setLexerBuffer( "12.3 * 0.96" );
do
{
token = yylex();
printToken( token );
}
while( token != LEX_EOF );
setLexerBuffer( "( A + B ) < ( C * D )" );
do
{
token = yylex();
printToken( token );
}
while( token != LEX_EOF );
yylex_destroy();
return 0;
}
此示例通过valgrind运行以验证内存正确性。
于 2021-03-11T23:50:28.630 回答
-1
我在这里找到了自己的例子。希望它对您有用:
于 2009-12-18T19:19:38.080 回答