您的位置:首页 > 其它

flex&bison 学习笔记(1)

2007-03-27 18:14 369 查看
最近用的项目是用脚本写GUI界面,空闲时间也想自己写个脚本系统玩一玩,以前用的都是别人写好的脚本引擎,比如:JavaScript、VBScript、lua……
自己没有研究过。准备工作当然是搜集资料了,先看了一篇教程《Implementing a Scripting Engine》,说得不错,打算也采用lex和yacc来做词法和语法的分析(全都自己写太累了,有现成的何必不用呢?)。
但是郁闷的是,该教程附带的例子只有一个lex词法分析的,yacc的没有,不管那么多,先跑起来看看,恩,不知所云,不过程序跑完整了。能把输入的文本按规则返回token。不过怎么编写lex文件还摸不到门道。
上网搜了半天关于yacc的资料,结果有语法文件的都编译不通过,郁闷!~~~~~~
今天决定分开来看,首先是flex文件,

LETTER [a-zA-Z_]
DIGIT [0-9]
STR \"[^\"]*\"
CHAR '{LETTER}'
WSPACE [ \t]+
bool "true"|"false"

%%

%%
int yywrap()
int lineno = 0;
#define ERROR_TOKEN 258
#define IF 259
#define ELSE 260
#define PRINT 261
#define INPUT 262
#define ASSIGN 263
#define EQUAL 264
#define NOTEQUAL 265
#define CONCAT 266
#define END_STMT 267
#define OPEN_PAR 268
#define CLOSE_PAR 269
#define BEGIN_CS 270
#define END_CS 271
#define ID 272
#define INTEGER 273
#define STRING 274

extern YYSTYPE yylval;
在.NET 2005下编译必须要包含io.h,否则会报告没有定义的函数 int __cdecl isatty(int)
lexsymb.h文件包含了几个函数的声明以及用来保存行数的全局变量:

extern int lineno;
extern int yyerror(char *msg);
extern int yylex();

接下来是yacc文件了:这是从网上找到的很简单的一个例子,修改了一下以和我的lex文件相符合:

%union {
char* str;
}
%{

#include <stdio.h>
#include <string.h>
#include <io.h>
#include <malloc.h>
#include "lexsymb.h"
%}
%token ERROR_TOKEN
%token IF
%token ELSE
%token PRINT
%token INPUT
%token ASSIGN
%token EQUAL
%token NOTEQUAL
%token CONCAT
%token END_STMT
%token OPEN_PAR
%token CLOSE_PAR
%token BEGIN_CS
%token END_CS
%token ID
%token INTEGER
%token STRING
%%
file : record file
| record
;
record : ID EQUAL INTEGER {
printf("%s is %s years old!!!\n", $1, $3); }
;
%%
int main()
{
yyparse();
return 0;
}
int yyerror(char *msg)
{
printf("Error encountered: %s \n", msg);
return 0;
}

yacc文件也跟lex文件一样分成三部分,用%%来分隔,
第一部分中的%union代码 声明了 Yacc 值栈,并且外部变量 yylval 和 yyval 有等于这个联合的类型。如果使用 -d 选项调用 Yacc,则把联合声明复制到 头文件中(我这里是parse.cpp.h)。二者选一的,联合也可以在头文件中声明,使用 typedef 来定义变量 YYSTYPE 去表示这个联合
token的定义也在第一部分,-d参数会把这些token的id复制到头文件中。
先了解了这么多,接下来的任务是yacc文件中规则的编写。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: