parse generator是Windows下替代bison的一款好软件,使用academic copy license时,可以无功能限制使用。网上有很多关于生成c的例子。这里来个c++的。
我是在VC6环境下的,关于配置的问题,我就不讲了,参看PG自带的帮助文件的“设置Visual C++ version 4.0及更高版本”一节。保证include files啊,source files啊等等都设置好了哈。
保证在项目设置中,库啊(通常是yld.lib),YYDEBUG预处理标记都添加好了。
对于PG安装目录下的\Cpp\Examples\calc中yacc文件calc.y,用PG编译出c语言的,这时拿输出的下编译好的h和c文件,编译肯定是没有问题的。
但如果你想搞成c++的,生成的cpp文件会在build时报错,会提示有undeclared identifier的yylval和yyparse。
这时,你需要更改yacc文件为:
#include <ctype.h>
#include <stdio.h>
#define YYSTYPE double
%}
%token NUMBER
%name myparser
// class definition
{
// place any extra class members here
virtual int yygettoken();
}
%%
lines : lines expr '\n' { printf("%g\n", $2); }
| lines '\n'
|
| error '\n' { yyerror("reenter last line:"); yyerrok(); }
;
expr : expr '+' term { $$ = $1 + $3; }
| expr '-' term { $$ = $1 - $3; }
| term
;
term : term '*' factor { $$ = $1 * $3; }
| term '/' factor { $$ = $1 / $3; }
| factor
;
factor : '(' expr ')' { $$ = $2; }
| '(' expr error { $$ = $2; yyerror("missing ')'"); yyerrok(); }
| '-' factor { $$ = -$2; }
| NUMBER
;
%%
int main(void)
{
int n = 1;
myparser parser;
if (parser.yycreate()) {
n = parser.yyparse();
}
return n;
}
int YYPARSERNAME::yygettoken()
{
// place your token retrieving code here
int c;
YYSTYPE YYFAR& yylval = *(YYSTYPE YYFAR*)yylvalptr;
while ((c = getchar()) == ' ');
if (c == '.' || isdigit(c)) {
ungetc(c, stdin);
scanf("%lf", &yylval);
return NUMBER;
}
return c;
}
可以看到改动有3处,第一处是添加了%name和yygettoken成员函数的声明;第二处是搞复杂了main函数;第三处就是添加了yygettoken成员函数的定义,用它取代了yylex函数。至此,用PG编译生成的c++输出文件就能在VC下build了。
http://hi.baidu.com/wangkai/blog/item/5cc815ce0bfa443db600c834.html
关于上面论述,我在VS2005环境下做过,发现有点问题,首先,把一个警告信息解决,按照上述程序编译,会有警告:
warning C4996: 'scanf' was declared deprecated
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\stdio.h(295) : see declaration of 'scanf'
1> Message: 'This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
关于产生原因和解决办法如下:
排除 vs2005 中的不安全函数警告:
下面的代码:
#include <stdio.h>
#include <minmax.h>
int main( )
{
int a,b,c;
scanf("%d,%d",&a,&b);
c=max(a,b);
printf("max=%d",c);
return 0;
}
使用vs2005编译时会遇到这样一个warning: warning C4996: 'scanf' was declared deprecated
其实 warning C4996的详细含义就是:'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.翻译过来,就是scanf的声明在VS2005中被认为是不安全的,让你使用scanf_S来代替。
知道了原因,那解决就方便了,只要在#include <stdio.h>前面添加
#define _CRT_SECURE_NO_DEPRECATE 或者 scanf函数修改为scanf_s即可。具体如下:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <minmax.h>
int main( )
{
int a,b,c;
scanf("%d,%d",&a,&b);
c=max(a,b);
printf("max=%d",c);
return 0;
}
或者
#include <stdio.h>
#include <minmax.h>
int main( )
{
int a,b,c;
scanf_s("%d,%d",&a,&b);
c=max(a,b);
printf("max=%d",c);
return 0;
}