flex bison的小问题

cnyu 2010-07-12 02:22:48
我想把一个包含函数的字符串用flex bison解析生成c代码,能够计算表达式的值,这个flex和bison的语法文件该怎么写?

例如: "abc" + substr("efghijklmn", 0, 3) + "xyz"
substr 是取子字符串的函数,substr("efghijklmn", 0, 3) 表示对字符串"efghijklmn"从第0个位置开始, 取3个字符, 得到子串"efg"
+ 表示连接2个字符串

则上述的表达式计算的结果为: abcefgxyz

要求能支持函数嵌套,如: substr(substr("efghijklmn", 0, 4), 0, 2)
得到结果ef
...全文
409 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnyu 2010-07-16
  • 打赏
  • 举报
回复
csdn应该增加一个编译原理和编译器的讨论区的, 遇到这类问题, 基本靠搜索才能找到
cnyu 2010-07-16
  • 打赏
  • 举报
回复
是呀, 幸亏他帮忙, 不然我得折腾好长时间呢
感觉这方面的东西还是挺有意思的, 功能也相当强悍,有空深入的学习一下
freshui 2010-07-16
  • 打赏
  • 举报
回复
mlee79是这方面的专家,当年我玩lex & yacc的时候基本上也是他指教的 :)
mLee79 2010-07-15
  • 打赏
  • 举报
回复
我只喜欢这样子的:

%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#if defined( _MSC_VER )
#define YY_NO_UNISTD_H
#endif

struct parser_context
{
char *input;
};

#define YYPARSE_PARAM parser
#define YYLEX_PARAM ((struct parser_context*)YYPARSE_PARAM)

union YYSTYPE;
int yylex ( union YYSTYPE* , struct parser_context* );
int yyparse ( void *YYPARSE_PARAM );

void yyerror( const char* msg ) {
fprintf( stderr , "[ERROR]--- %s ---\n" , msg );
}
%}

%pure_parser

%union {
int iVal;
char * sVal;
}

%token SUBSTR STRLEN I2A A2I
%token<iVal> NUMBER
%token<sVal> STRING

%type<iVal> iExpr
%type<sVal> sExpr

%destructor { free($$); } STRING sExpr

%left '+' '-'
%left '*' '/'
%right UADD USUB

%%

goal:
line
|
goal line
;

line:
iExpr '\n' { printf( "[INT]result = %d\n" , $1 ); }
|
sExpr '\n' { printf( "[STR]result = %s\n" , $1 ); free($1); }
|
'\n'
;

iExpr:
NUMBER
|
STRLEN '(' sExpr ')' { $$ = strlen( $3 ); free( $3 ); }
|
iExpr '+' iExpr { $$ = $1 + $3; }
|
iExpr '-' iExpr { $$ = $1 - $3; }
|
iExpr '*' iExpr { $$ = $1 * $3; }
|
iExpr '/' iExpr { if( $3 == 0 ) YYABORT; $$ = $1 / $3; }
|
'+' iExpr %prec UADD { $$ = $2 ; }
|
'-' iExpr %prec USUB { $$ = -$2; }
|
'(' iExpr ')' { $$ = $2; }
|
A2I '(' sExpr ')' { $$ = atoi( $3 ); free( $3 ); }
;

sExpr:
STRING
|
I2A '(' iExpr ')' { $$ = malloc( 16 ); sprintf( $$ , "%d" , $3 ); }
|
SUBSTR '(' sExpr ',' iExpr ',' iExpr ')' {
char *input = $3 , *result = NULL;
int beg = $5 , len = $7;
int slen = strlen( input );

if( beg < 0 ) beg = 0;
if( beg >= slen || len == 0 )
result = strdup( "" );
else if( len < 0 || beg + len >= slen )
result = strdup( input + beg );
else {
input[beg+len] = 0;
result = strdup( input + beg );
}
$$ = result;
free( input );
}
|
sExpr '+' sExpr {
$$ = malloc( strlen( $1 ) + strlen( $3 ) + 1 );
strcpy( $$ , $1 ); strcat( $$ , $3 ); free($1); free($3); }
|
'(' sExpr ')' { $$ = $2; }
;

%%

int main()
{
char line[ 32*1024 + 1 ] = "";
struct parser_context parser;

while( fgets( line , sizeof( line ) - 1 , stdin ) )
{
parser.input = line;
yyparse( &parser );
}
return 0;
}

int yylex ( union YYSTYPE* yylval , struct parser_context* parser )
{
char *input = parser->input;

char *text , *text_bak = NULL;
int curr , backup = 0 , action , yyc;

static const unsigned char yy_accept[33] =
{ 0,
0, 0, 11, 9, 8, 7, 7, 9, 5, 9,
9, 9, 8, 7, 0, 6, 5, 0, 0, 0,
0, 3, 4, 0, 0, 0, 0, 0, 0, 2,
1, 0
} ;

static const unsigned char yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 2, 2, 3,
1, 2, 4, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 5, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 6, 6, 7,
6, 6, 6, 6, 6, 6, 6, 1, 1, 1,
1, 1, 1, 1, 8, 9, 1, 1, 10, 1,
1, 1, 11, 1, 1, 12, 1, 13, 1, 1,
1, 14, 15, 16, 17, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 8, 9, 1, 1,

10, 1, 1, 1, 11, 1, 1, 12, 1, 13,
1, 1, 1, 14, 15, 16, 17, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
} ;

static const unsigned char yy_meta[18] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1
} ;

static const unsigned char yy_base[34] =
{ 0,
0, 0, 43, 44, 40, 44, 38, 35, 12, 32,
31, 4, 35, 44, 31, 30, 16, 23, 25, 18,
22, 44, 44, 18, 14, 18, 11, 13, 11, 44,
44, 44, 23
} ;

static const unsigned char yy_def[34] =
{ 0,
32, 1, 32, 32, 32, 32, 32, 33, 32, 32,
32, 32, 32, 32, 33, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 0, 32
} ;

static const unsigned char yy_nxt[62] =
{ 0,
4, 5, 6, 7, 8, 9, 9, 10, 4, 4,
11, 4, 4, 4, 12, 4, 4, 17, 17, 20,
21, 17, 17, 15, 31, 30, 29, 28, 27, 26,
25, 24, 23, 22, 15, 16, 13, 19, 18, 16,
14, 13, 32, 3, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32
} ;

static const unsigned char yy_chk[62] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 9, 9, 12,
12, 17, 17, 33, 29, 28, 27, 26, 25, 24,
21, 20, 19, 18, 16, 15, 13, 11, 10, 8,
7, 5, 3, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32
} ;

if( NULL == input )
return 0;

while( 1 )
{
if( 0 == input[0] )
{
parser->input = NULL;
return 0;
}

curr = 1;
text = input;

do {
if( 0 == input[0] )
break;
yyc = yy_ec[*(const unsigned char*)input++];
while( yy_chk[ yy_base[ curr ] + yyc ] != curr )
if( ( curr=yy_def[ curr ] ) >= sizeof(yy_accept)/sizeof(yy_accept[0]) )
yyc = yy_meta[ yyc ];
curr = yy_nxt[ yy_base[ curr ] + yyc ];
if( yy_accept[ curr ] )
{
backup = curr ;
text_bak = input;
}
} while( yy_base[curr] != yy_base[ sizeof(yy_accept)/sizeof(yy_accept[0]) - 1 ] );

action = yy_accept[ curr ];
if( 0 == action )
{
curr = backup;
input = text_bak;
action = yy_accept[ curr ];
}

parser->input = input;
switch( action )
{
case 1:
return SUBSTR;
case 2:
return STRLEN;
case 3:
return A2I;
case 4:
return I2A;
case 5:
yylval->iVal = atoi( text );
return NUMBER;
case 6:
{
char *p , *s;
s = text + 1;
input[-1] = 0;
p = yylval->sVal = (char*)malloc( input - text );

while( *s ) {
if( *s == '\"' && s[1] == 0 )
break;
if( *s == '\"' && s[1] == '\"' )
*p++ = '\"' , s += 2;
else
*p++ = *s++;
}
*p = 0;
return STRING;
}
case 7:
return '\n';
case 8:
break;
case 9:
return text[0];
}
}

return 0;
}

cnyu 2010-07-15
  • 打赏
  • 举报
回复
我定义了一个全局变量:char g_result[1024];
将解析的结果存放到全局变量中
line:
iExpr '\n' { printf( "[INT]result = %d\n" , $1 ); sprintf(g_result, "%d", $1); }
|
sExpr '\n' { printf( "[STR]result = %s\n" , $1 ); sprintf(g_result, "%s", $1); free($1); }
|
'\n'
;

这里取得结果
int nParse = 0;
char input[1024] = {0};
memset(g_result, 0, sizeof(g_result));
sprintf(input, "%s", "\"hello\"+\" world\"+substr(\",nihaoma?\", 2, 3)\n");
yy_switch_to_buffer(yy_scan_string(input));

nParse = yyparse();

printf("%s\n", g_result);

目前看起来还可以, 但是感觉不是很好
cnyu 2010-07-15
  • 打赏
  • 举报
回复

int main(void)
{
char result[1024] = {0};
sprintf(result, "%s", "\"hello\"+\" world\"+substr(\",nihaoma?\", 2, 3)\n");
yy_switch_to_buffer(yy_scan_string(result));

yyparse();
fread(result, sizeof(result), 1, yyout);
printf("%s\n", result);

return 0;
}


这种方式, 我发现只能传入参数, 可是得不到分析结果呀
cnyu 2010-07-15
  • 打赏
  • 举报
回复
我刚刚接触, 能不能详细一点呀, 谢谢了
mLee79 2010-07-15
  • 打赏
  • 举报
回复
flex 可以定制 skl 文件, 不过不是很好用, 最好的办法是只用 flex 生成 DFA , 代码自己写, bison 用 pure parser 模式...

cnyu 2010-07-15
  • 打赏
  • 举报
回复
再问一下mLee79:
int main()
{
return yyparse();
}
是从键盘获得输入,然后直接打印到输出
我现在想通过参数的形式,传入分析字符串,然后得到分析结果, 该如何做?
比如
char* analyze(char* s)
{
// 如何把参数传给yyparse()
yyparse();
// 如何获取yyparse的分析结果
}

谢谢

cnyu 2010-07-15
  • 打赏
  • 举报
回复
真是太感谢了, 学了不少东西
赶紧拷下来, 作为范例, 好好研究研究
mLee79 2010-07-15
  • 打赏
  • 举报
回复
那些是flex生成的DFA状态表, 要包含处理结果, 就弄成这样:

%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#if defined( _MSC_VER )
#define YY_NO_UNISTD_H
#endif

struct parser_context
{
char *input;

int type ;
int iResult;
char* sResult;
};

#define YYPARSE_PARAM parser
#define YYLEX_PARAM ((struct parser_context*)YYPARSE_PARAM)

union YYSTYPE;
int yylex ( union YYSTYPE* , struct parser_context* );
int yyparse ( void *YYPARSE_PARAM );

void yyerror( const char* msg ) {
fprintf( stderr , "[ERROR]--- %s ---\n" , msg );
}
%}

%pure_parser

%union {
int iVal;
char * sVal;
}

%token SUBSTR STRLEN I2A A2I
%token<iVal> NUMBER
%token<sVal> STRING

%type<iVal> iExpr
%type<sVal> sExpr

%destructor { free($$); } STRING sExpr

%left '+' '-'
%left '*' '/'
%right UADD USUB

%%

goal:
line
|
goal line
;

line:
iExpr '\n' {
((struct parser_context*)YYPARSE_PARAM)->type = 0;
((struct parser_context*)YYPARSE_PARAM)->iResult = $1; }
|
sExpr '\n' {
((struct parser_context*)YYPARSE_PARAM)->type = 1;
((struct parser_context*)YYPARSE_PARAM)->sResult = $1; }
|
'\n'
;

iExpr:
NUMBER
|
STRLEN '(' sExpr ')' { $$ = strlen( $3 ); free( $3 ); }
|
iExpr '+' iExpr { $$ = $1 + $3; }
|
iExpr '-' iExpr { $$ = $1 - $3; }
|
iExpr '*' iExpr { $$ = $1 * $3; }
|
iExpr '/' iExpr { if( $3 == 0 ) YYABORT; $$ = $1 / $3; }
|
'+' iExpr %prec UADD { $$ = $2 ; }
|
'-' iExpr %prec USUB { $$ = -$2; }
|
'(' iExpr ')' { $$ = $2; }
|
A2I '(' sExpr ')' { $$ = atoi( $3 ); free( $3 ); }
;

sExpr:
STRING
|
I2A '(' iExpr ')' { $$ = malloc( 16 ); sprintf( $$ , "%d" , $3 ); }
|
SUBSTR '(' sExpr ',' iExpr ',' iExpr ')' {
char *input = $3 , *result = NULL;
int beg = $5 , len = $7;
int slen = strlen( input );

if( beg < 0 ) beg = 0;
if( beg >= slen || len == 0 )
result = strdup( "" );
else if( len < 0 || beg + len >= slen )
result = strdup( input + beg );
else {
input[beg+len] = 0;
result = strdup( input + beg );
}
$$ = result;
free( input );
}
|
sExpr '+' sExpr {
$$ = malloc( strlen( $1 ) + strlen( $3 ) + 1 );
strcpy( $$ , $1 ); strcat( $$ , $3 ); free($1); free($3); }
|
'(' sExpr ')' { $$ = $2; }
;

%%

int main()
{
char line[ 32*1024 + 1 ] = "";
struct parser_context parser;

while( fgets( line , sizeof( line ) - 1 , stdin ) )
{
parser.input = line;
if( 0 == yyparse( &parser ) ) {
if( parser.type == 0 ) {
printf( "[INT]result == %d\n" , parser.iResult );
}
else {
printf( "[STR]result == %s\n" , parser.sResult );
free( parser.sResult );
}
}
}
return 0;
}

int yylex ( union YYSTYPE* yylval , struct parser_context* parser )
{
char *input = parser->input;

char *text , *text_bak = NULL;
int curr , backup = 0 , action , yyc;

static const unsigned char yy_accept[33] =
{ 0,
0, 0, 11, 9, 8, 7, 7, 9, 5, 9,
9, 9, 8, 7, 0, 6, 5, 0, 0, 0,
0, 3, 4, 0, 0, 0, 0, 0, 0, 2,
1, 0
} ;

static const unsigned char yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 2, 2, 3,
1, 2, 4, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 5, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 6, 6, 7,
6, 6, 6, 6, 6, 6, 6, 1, 1, 1,
1, 1, 1, 1, 8, 9, 1, 1, 10, 1,
1, 1, 11, 1, 1, 12, 1, 13, 1, 1,
1, 14, 15, 16, 17, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 8, 9, 1, 1,

10, 1, 1, 1, 11, 1, 1, 12, 1, 13,
1, 1, 1, 14, 15, 16, 17, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
} ;

static const unsigned char yy_meta[18] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1
} ;

static const unsigned char yy_base[34] =
{ 0,
0, 0, 43, 44, 40, 44, 38, 35, 12, 32,
31, 4, 35, 44, 31, 30, 16, 23, 25, 18,
22, 44, 44, 18, 14, 18, 11, 13, 11, 44,
44, 44, 23
} ;

static const unsigned char yy_def[34] =
{ 0,
32, 1, 32, 32, 32, 32, 32, 33, 32, 32,
32, 32, 32, 32, 33, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 0, 32
} ;

static const unsigned char yy_nxt[62] =
{ 0,
4, 5, 6, 7, 8, 9, 9, 10, 4, 4,
11, 4, 4, 4, 12, 4, 4, 17, 17, 20,
21, 17, 17, 15, 31, 30, 29, 28, 27, 26,
25, 24, 23, 22, 15, 16, 13, 19, 18, 16,
14, 13, 32, 3, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32
} ;

static const unsigned char yy_chk[62] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 9, 9, 12,
12, 17, 17, 33, 29, 28, 27, 26, 25, 24,
21, 20, 19, 18, 16, 15, 13, 11, 10, 8,
7, 5, 3, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32
} ;

if( NULL == input )
return 0;

while( 1 )
{
if( 0 == input[0] )
{
parser->input = NULL;
return 0;
}

curr = 1;
text = input;

do {
if( 0 == input[0] )
break;
yyc = yy_ec[*(const unsigned char*)input++];
while( yy_chk[ yy_base[ curr ] + yyc ] != curr )
if( ( curr=yy_def[ curr ] ) >= sizeof(yy_accept)/sizeof(yy_accept[0]) )
yyc = yy_meta[ yyc ];
curr = yy_nxt[ yy_base[ curr ] + yyc ];
if( yy_accept[ curr ] )
{
backup = curr ;
text_bak = input;
}
} while( yy_base[curr] != yy_base[ sizeof(yy_accept)/sizeof(yy_accept[0]) - 1 ] );

action = yy_accept[ curr ];
if( 0 == action )
{
curr = backup;
input = text_bak;
action = yy_accept[ curr ];
}

parser->input = input;
switch( action )
{
case 1:
return SUBSTR;
case 2:
return STRLEN;
case 3:
return A2I;
case 4:
return I2A;
case 5:
yylval->iVal = atoi( text );
return NUMBER;
case 6:
{
char *p , *s;
s = text + 1;
input[-1] = 0;
p = yylval->sVal = (char*)malloc( input - text );

while( *s ) {
if( *s == '\"' && s[1] == 0 )
break;
if( *s == '\"' && s[1] == '\"' )
*p++ = '\"' , s += 2;
else
*p++ = *s++;
}
*p = 0;
return STRING;
}
case 7:
return '\n';
case 8:
break;
case 9:
return text[0];
}
}

return 0;
}

cnyu 2010-07-15
  • 打赏
  • 举报
回复
你这些static的数组比如yy_def, yy_nxt 里面的数字都是什么意思呀?
cnyu 2010-07-15
  • 打赏
  • 举报
回复
非常感谢, 那你的这个parser_context.input 既包含输入,又包含处理的结果吗?
cnyu 2010-07-14
  • 打赏
  • 举报
回复
问题解决了, 太感谢了
你真是太牛了,佩服佩服
cnyu 2010-07-14
  • 打赏
  • 举报
回复
哦, 谢谢指点, 我重新下载一个新版本
mLee79 2010-07-14
  • 打赏
  • 举报
回复
嗯, 你的 bison 版本好像稍微有点特别 ...

flex --version && bison --version
flex 2.5.33
bison (GNU Bison) 2.3

一般偶不用 flex 生成代码, 只用 flex 生成DFA表, 如果用 flex 生成文件, 偶都稀饭弄成 .inl ...
flex -o scanner.inl scanner.l



cnyu 2010-07-14
  • 打赏
  • 举报
回复
#include "scanner.inl"
是什么文件, 楼主用的是什么版本的flex 和 bison
我的是
flex version 2.5.4
GNU Bison version 1.28

我改了一下文件名: substr.l 和 substr.y
flex substr.l 能通过
bison -d substr.y 结果如下:

C:\lexyacc\test>bison -d substr.y
substr.y:28: unrecognized: %destructor
substr.y:28: Skipping to next %


还请指点一下,谢谢
cnyu 2010-07-14
  • 打赏
  • 举报
回复
多谢楼上的, 太牛了
mLee79 2010-07-14
  • 打赏
  • 举报
回复
我真无聊:

scanner.l

%{
%}

%option caseless

%%

substr { return SUBSTR; }
strlen { return STRLEN; }
a2i { return A2I; }
i2a { return I2A; }
[[:digit:]]+ { yylval.iVal = atoi( yytext ); return NUMBER; }

\"([^\"]|\"\")*\" {
char *p = yytext , *s = yytext + 1;
while( *s ) {
if( *s == '\"' && s[1] == 0 )
break;
if( *s == '\"' && s[1] == '\"' )
*p++ = '\"' , s += 2;
else
*p++ = *s++;
}
*p = 0;
yylval.sVal = strdup( yytext );
return STRING;}



\r\n|\r|\n { return '\n'; }

[ \t\b\f]+

. { return yytext[0]; }
%%

int yywrap()
{
return 1;
}



grammar.y

%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#if defined( _MSC_VER )
#define YY_NO_UNISTD_H
#endif

int yylex();
void yyerror( const char* msg ) {
fprintf( stderr , "[ERROR]--- %s ---\n" , msg );
}
%}

%union {
int iVal;
char * sVal;
}

%token SUBSTR STRLEN I2A A2I
%token<iVal> NUMBER
%token<sVal> STRING

%type<iVal> iExpr
%type<sVal> sExpr

%destructor { free($$); } STRING sExpr

%left '+' '-'
%left '*' '/'
%right UADD USUB

%%

goal:
line
|
goal line
;

line:
iExpr '\n' { printf( "[INT]result = %d\n" , $1 ); }
|
sExpr '\n' { printf( "[STR]result = %s\n" , $1 ); free($1); }
|
'\n'
;

iExpr:
NUMBER
|
STRLEN '(' sExpr ')' { $$ = strlen( $3 ); free( $3 ); }
|
iExpr '+' iExpr { $$ = $1 + $3; }
|
iExpr '-' iExpr { $$ = $1 - $3; }
|
iExpr '*' iExpr { $$ = $1 * $3; }
|
iExpr '/' iExpr { if( $3 == 0 ) YYABORT; $$ = $1 / $3; }
|
'+' iExpr %prec UADD { $$ = $2 ; }
|
'-' iExpr %prec USUB { $$ = -$2; }
|
'(' iExpr ')' { $$ = $2; }
|
A2I '(' sExpr ')' { $$ = atoi( $3 ); free( $3 ); }
;

sExpr:
STRING
|
I2A '(' iExpr ')' { $$ = malloc( 16 ); sprintf( $$ , "%d" , $3 ); }
|
SUBSTR '(' sExpr ',' iExpr ',' iExpr ')' {
char *input = $3 , *result = NULL;
int beg = $5 , len = $7;
int slen = strlen( input );

if( beg < 0 ) beg = 0;
if( beg >= slen || len == 0 )
result = strdup( "" );
else if( len < 0 || beg + len >= slen )
result = strdup( input + beg );
else {
input[beg+len] = 0;
result = strdup( input + beg );
}
$$ = result;
free( input );
}
|
sExpr '+' sExpr {
$$ = malloc( strlen( $1 ) + strlen( $3 ) + 1 );
strcpy( $$ , $1 ); strcat( $$ , $3 ); free($1); free($3); }
|
'(' sExpr ')' { $$ = $2; }
;

%%

#include "scanner.inl"

int main()
{
return yyparse();
}


运行结果
1+2-3
[INT]result = 0
substr( "12312312" , 3 , 2 )
[STR]result = 12
"abc" + substr("efghijklmn", 0, 3) + "xyz"
[STR]result = abcefgxyz
substr(substr("efghijklmn", 0, 4), 0, 2)
[STR]result = ef
a2i( substr( substr(substr("efghijklmn", 1+2-3-1, 4), 0, 2) + "123" , 3 , 5 ) )
+ 10 * 2
[INT]result = 43

cnyu 2010-07-14
  • 打赏
  • 举报
回复
看起来有些乱, 重新写一下吧:

%{
#include <stdio.h>
#include <stdlib.h>

void yyerror(char*);
#include "cal.tab.h"
char buf[1024];
char* s;

char* removequote(char* s);
void substr(char *s, int pos, int count, char* substr);
%}
%x STRING

%%
"substr" return SUBSTR;
\"(\\.|[^\\"])*\" { strcpy(buf, yytext); yylval = removequote(yytext); return STR;}
[0-9]+ {yylval = strdup(yytext); return INT;}
"," return (',');
"(" return ('(');
")" return (')');
"+" return ('+');
[\n] return *yytext;

[\t] ;
. yyerror("invalid char\n");

%%
int yywrap(void)
{
return 1;
}

char* removequote(char* s)
{
char szValue[1024];
char szLine[1024];
int len;

len = strlen(s);
strcpy(szLine, s);
strcpy(szValue, &szLine[1]);
szValue[len - 2] = 0;

s = szValue;

return s;
}

void substr(char *s, int pos, int count, char* substr)
{
//printf("%s, %d, %d\n", s, pos, count);
//return s;
int len, i, j;
len = strlen(s);
for ( i = pos, j = 0; i < pos + count; )
substr[j++] = s[i++];

substr[j] = 0;
}



%{
int yylex(void);
void yyerror(char*);

char szTmp[1024];
%}
%token STR INT SUBSTR
%left '+'
%%
program:
program expr '\n' { printf("%s\n", $2); exit(0);}
|
;
expr:
STR {$$=$1;}
| SUBSTR '(' STR ',' INT ',' INT ')'
{
printf("$3=%s,$5=%s,$7=%s\n", $3, $5, $7);
substr($3, atoi($5), atoi($7), szTmp);
$$ = szTmp;
}
| expr '+' expr
{
printf("\n$1=%s, $3=%s\n", $1, $3);
strcat(szTmp, $1);
strcat(szTmp, $3);
$$ = szTmp;
}
;
%%
void yyerror(char *s)
{
fprintf(stderr, "%s\n", s);
return;
}

int main(void)
{
yyparse();
return 0;
}


加载更多回复(6)

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧