ser Generator使用说明

Parser Generator使用说明

5913人阅读 评论(7) 收藏 举报

Parser Generator的使用说明

最近1个星期,大致学习了一下lex,虽然在windows系统上它并没有我所期望的强大,在调试和编写代码都遇到了不少困难,但是总体来说Parser Generator还是让我体会到了lex编程的快捷, 为了自己加深印象把一些参考资料和认识总结了一下.

<!--[if !supportLists]-->1.     <!--[endif]-->parser generator是什么?

它是一款在windows下编写lex/yacc程序的工具.可以到

http://www.bumblebeesoftware.com/downloads.htm

下载

<!--[if !supportLists]-->2.     <!--[endif]-->parser generator的使用方法

这里只以vc6.0为例,首先打开parser generator编辑器,选择Project->LibBuilder

LibBuilder对话框中选中Visual C++(32-bit),按属性键Properties后确以下设置

Script file name                        ./Cpp/Script/msvc32.lbs

Name                                    Visual C++(32-bit)

Directory                               msvc32

Compiler Version                         Version 6

Unicode                                  True

Treat wchar_t as Built-in Type            False

Compiler Bin Directory             安装路径/Microsoft Visual Studio/Vc98/bin

Compiler Bin Directory(2) 安装路径/Microsoft Visual Studio/Common/MSDev98/bin

Compiler Include Directory      安装路径/Microsoft Visual Studio/Vc98/include

Compiler Include Directory(2)               

Compiler Library Directory          安装路径/Microsoft Visual Studio/Vc98/lib

Compiler Library Directory(2)               

Libraries下的库文件全部选中后ok

LibBuilder对话框->Build(编译过程可能几分钟)

编译完成后我们就可以使用parser generator编写lex或是yacc程序了

Project->ParserWizard

Step1 工程设定(一点需要注意语言可以选择c或是c++java)

Step2 工程设定(默认创建带main函数的yacc文件和lex文件)

Step3 yacc文件设定

Step4 lex文件设定

 

Lexyacc的语法参考http://www.ibm.com/developerworks/cn/linux/sdk/lex/

编辑好代码后Project->RebBuild All在你创建好的工程下自动生成Step1选定语言的文件(.h/..c/.cpp/.java)

之后在vc6.0加入如下设置

Tool->Option-> directory

Bin file :

安装目录/PARSER GENERATOR 2/BIN

Include file:

安装目录/PARSER GENERATOR 2/CPP/INCLUDE

Library file

安装目录/PARSER GENERATOR 2/CPP/LIB/MSVC32

Soure file

安装目录/PARSER GENERATOR 2/CPP/SOURCE

创建vc6.0工程

将生成文件复制到vc6.0创建工程下

Source filesHeader Files中加入生成文件(.h/.c/.cpp)

在工程设定中Project->Settings For box选中win32 debug

c/c++ ->Category选中General ->Preprocessor Definitions加入YYDEBUG

在工程Project设定Project->Settings For box中选中all

link -> Category选中General->Object/Library Modules中加入yld.lib

这里需要注意的是yld.libparser generatorDUBUG单线程版本,对于vc的控制台程序是可以的,如果使用了MFC或是Windows applications程序则需要对应下表追加

Library(DEBUG)

Run-time Library

Description

yld.lib

Debug Single-Threaded

单线程静态链接库(DEBUG版本)

ylmtd.lib

Debug Multithreaded

多线程静态链接库(DEBUG版本)

ylmtrd.lib

Debug Multithreaded DLL

多线程静态链接库当run time library 使用动态库(DEBUG版本)

ylmtrid.lib    

Debug Multithreaded DLL

多线程动态链接库当run time library 使用动态库(DEBUG版本)

 

Library(RELEASE)

Run-time Library

Description

yl.lib

Single-Threaded

单线程静态链接库(RELEASE版本)

ylmt.lib

Multithreaded

多线程静态链接库(RELEASE版本)

ylmtr.lib

Multithreaded DLL      

多线程静态链接库当run time library 使用动态库(RELEASE版本)

ylmtri.lib

Multithreaded DLL      

多线程动态链接库当run time library 使用动态库(RELEASE版本)

如果使用了动态库版本需要在程序运行环境中追加DLL的地址

安装目录/PARSER GENERATOR 2/CPP/LIB/MSVC32

如果需要链接yacc或是lexdll.Preprocessor Definitions下加入YYDLL.

 

这样就可以使用vc6.0lex生成文件进行编译了

3PG2的默认输FILE *,怎样转char *?
PG2
提供了两方法,一是重定yyinput,二是重定yygetchar实际使用中后者方便,因yyinput除了yygetchar之外需要负责lineno量的增加。
yygetchar通常这样
int yygetchar(void)
{
     if (* inputstring=='/0')
     {
           return -1;
     }
     return (unsigned char) * inputstring++;
}
唯一要注意的就是char *的末尾要返回一个-1代表EOF,使得yyinput停止。(感luocong的提醒)。

4
、同理,yyoutput
FILE *char *
直接
yytext操作既可,yytext就是char[]

3,4说明转自

http://blog.csdn.net/tankaiha/archive/2005/12/13/551457.aspx

总体来说lex/yacc比起自己编写分析程序要快的多,但是不足点就是错误的调试会非常困难,需要把.lex/.l.yacc/.y文件加入工程调试,每次变更都需要重新编译parser generator工程,然后再次粘贴,lex的语法熟练度可能决定了效率,新手基于模型为基础进行研究逐步认识parser generator是最佳的学习方法,

Lex的自带例程在/Parser Generator 2/Cpp/Examples ,在这对其中的class(四则计算器)做下简单说明

lexer.l文件

%{              //%{ %}中的c代码将被复制到.cpp文件中

#include <stdlib.h>

#include <math.h>

#include <assert.h>

#include "parser.h"//自动生成头文件必须包含

%}

 

// include file

%include {              //%include {}里的代码复制到对应的.h文件中,这里声明calc_parser

class calc_parser;   // symboltable是为在下面calc_lexer::create函数能够找到使用类型的提前

class symboltable;  //声明

}

 

// lexical analyser name

%name calc_lexer         //%name指定继承自lexer的类名{}中为类成员声明,类的声明将被解//释到.h文件中

// class definition

{

// Attributes

protected:

        symboltable* m_symboltable;             // the symbol table

 

// Operations

public:

        int create(calc_parser* parser, symboltable* symboltable);

       

        // attribute commands

        double number() const;

        symbol* id() const;

}

 

// constructor

{

        // do nothing

}

 

// macros

exponent        ([Ee][+-]?[0-9]+)  //科学计算方定义为exponent

 

%%

 

%{

// extract yylval for use later on in actions

YYSTYPE& yylval = *(YYSTYPE*)yyparserptr->yylvalptr;//指定yylval值的类型

%}

 

// 对于数字的规则处理 |表示或,|下一个算式使用的规则与第一个相同{}中是规则执行代码

[0-9]+"."[0-9]*{exponent}?      |

"."[0-9]+{exponent}?            |

[0-9]+{exponent}?                       { yylval.value = number(); return NUMBER; }

 

//对于3角函数的规则处理

"sin"                                           { return SIN; }

"cos"                                           { return COS; }

"tan"                                           { return TAN; }

 

// 对于变量的规则处理

[a-zA-Z_][a-zA-Z0-9_]*          { yylval.symbol = id(); return ID; }

 

//对于符号的规则处理

"="                                                     { return '='; }

"+"                                                     { return '+'; }

"-"                                                     { return '-'; }

"*"                                                     { return '*'; }

"/"                                                     { return '/'; }

"("                                                     { return '('; }

")"                                                     { return ')'; }

 

// 对于特殊符号的处理

[ /t]                                           { /* do nothing */ }

/n                                                      { return '/n'; }

 

.                                                       { printf("invalid character '0x%02x'/n", (unsigned int)yytext[0]); }

 

%%

 

/

// 以下都是对成员函数的实现,将被复制到.cpp文件中

 

int calc_lexer::create(calc_parser* parser, symboltable* symboltable)

{

        assert(parser != NULL);

        assert(symboltable != NULL);

       

        m_symboltable = symboltable;

        return yycreate(parser);

}

 

/

// calc_lexer attribute commands

 

double calc_lexer::number() const

{

        errno = 0;              // clear error flag

        char* endp;

        double d = strtod(yytext, &endp);

        if ((d == +HUGE_VAL || d == -HUGE_VAL) && errno == ERANGE) {

                printf("number too big/n");

        }

        return d;

}

 

symbol* calc_lexer::id() const

{

        symbol* p = m_symboltable->install(yytext);

        return p;

}//lexer.l end

 

parser.y文件

%{                      //%{ %}中的c代码将被复制到.cpp文件中

#include <math.h>

%}

 

// include file

%include {              //%include {}里的代码复制到对应的.h文件中,这里声明symbol

 // 是为在下面calc_parser:: assign函数能够找到使用类型的提前

 //声明

// forward references

class symbol;

}

 

//%union表示使用联合体声明yytest的类型可能有2,也就是lex返回的标记的值的类型(//一个标记都会有一个值)

%union {

        symbol* symbol;

        double value;

}

 

// nonterminals

%type <value> expr  //%type是声明变量exprdouble类型,这里要注意的是<>声明的类型必//须是在%union中定义的变量

//这里要注意下越是后声明的越高

%right '='          //%right声明=为右结合

%left '+', '-'  //%left 声明+ -为左结合

%left '*', '/'        //%left 声明* /为左结合

%right UMINUS     //%right声明UMINUS为右结合,此优先级最高

 

%token <value> NUMBER //%token声明标记NUMBER和其类型,%type注意点一样

%token <symbol> ID     //声明标记ID的类型,%type注意点一样

 

// keywords

%token SIN           //声明标记SIN,因为本身的值没有用途所以不对其类型特殊声明

%token COS           //声明标记COS,因为本身的值没有用途所以不对其类型特殊声明

%token TAN           //声明标记TAN,因为本身的值没有用途所以不对其类型特殊声明

 

// include file

%include {

#include "symbol.h"  //%{ %}中的c代码将被复制到.h文件中

#include "lexer.h"

}

 

// parser name

%name calc_parser   //%name指定继承自lexer的类名{}中为类成员声明,类的声明将被解

//释到.h文件中

// class definition

{

// 类成员声明

protected:

        symboltable m_symboltable;              // the symbol table

        calc_lexer m_lexer;                             // the lexical analyser

       

// Operations

public:

        int create();

       

        // attribute commands

        double assign(symbol* id, double value);

        double divide(double dividend, double divisor);

}

 

// constructor

{

        // do nothing

}

 

%%

lines

        : lines line

        | /* empty */

        ;

 

line

        : expr '/n'                                     { printf("%g/n", (double)$1); }

        | error '/n'                            { yyerrok(); }

        ;

//这里只对expr进行说明$$是冒号左边表达式的值   $1为右边第一个表达式的值

$2为右边第二个表达式的值  $3为右边第三个表达式的值,以此类推.

expr

        : ID '=' expr                           { $$ = assign($1, $3); }//变量保存

        | expr '+' expr                         { $$ = $1 + $3; }

        | expr '-' expr                         { $$ = $1 - $3; }

        | expr '*' expr                         { $$ = $1 * $3; }

        | expr '/' expr                         { $$ = divide($1, $3); }//除法判断

        | '(' expr ')'                          { $$ = $2; }

        | '-' expr %prec UMINUS         { $$ = -$2; }

// %prec说明'-' expr表达式的优先级和UMINUS一样.

        | NUMBER                                        { $$ = $1; }

        | ID                                            { $$ = $1->m_value; }

        | SIN '(' expr ')'                      { $$ = sin($3); }

        | COS '(' expr ')'                      { $$ = cos($3); }

        | TAN '(' expr ')'                      { $$ = tan($3); }

        ;

 

%%

 

/

//以下都是对成员函数的实现,将被复制到.cpp文件中

 

 

int main(void)

{

        int n = YYEXIT_FAILURE;

       

        calc_parser parser;

        if (parser.create()) {

                n = parser.yyparse();

        }

        return n;

}

 

/

// calc_parser commands

 

int calc_parser::create()

{

        if (!yycreate(&m_lexer)) {

                return 0;

        }

        if (!m_lexer.create(this, &m_symboltable)) {

                return 0;

        }

        return 1;       // success

}

 

/

// calc_parser attribute commands

 

double calc_parser::assign(symbol* id, double value)

{

        assert(id != NULL);

 

        id->m_value = value;

        return id->m_value;

}

 

double calc_parser::divide(double a, double b)

{

        if (b == 0) {

                printf("division by zero/n");

                yythrowerror();         // causes a syntax error

                return 0;

        }

        else {

                return a / b;

        }

}

更多详细参考可以查看Parser Generator Help帮助文档

以上都是作者的辛苦劳动,转载请注明出处.

更多 0
相关主题推荐
visual studio 多线程 visual c++ 对话框 character
相关博文推荐
【Java核心技术——多线程】
操作系统(3)进程及其实现
CString头文件
mfc深入浅出 系列 深入浅出mfc 第...
Java 线程同步异步学习
黑马程序员01_多线程
win7中VC6.0 visual C+...
关于JAVA多线程Runnable和Th...
id="google_ads_frame1" height="90" marginheight="0" src="http://googleads.g.doubleclick.net/pagead/ads?client=ca-pub-1076724771190722&output=html&h=90&slotname=4497271841&adk=1868520242&w=728&lmt=1393734404&ea=0&flash=12.0.0.70&url=http%3A%2F%2Fblog.csdn.net%2Fxujianlane%2Farticle%2Fdetails%2F2801204&dt=1393734404343&shv=r20140220&cbv=r20140226&saldr=sb&correlator=1393734404358&frm=20&ga_vid=1724069759.1393734404&ga_sid=1393734404&ga_hid=442748419&ga_fc=0&u_tz=480&u_his=1&u_java=1&u_h=670&u_w=1192&u_ah=670&u_aw=1138&u_cd=32&u_nplug=0&u_nmime=0&dff=arial&dfs=12&adx=298&ady=16062&biw=1120&bih=490&eid=317150313&oid=3&ref=http%3A%2F%2Fblog.csdn.net%2Fxujianlane%2Farticle%2Fdetails%2F2801204&rx=0&eae=4&docm=7&brdim=54%2C143%2C%2C%2C1138%2C%2C%2C%2C%2C&vis=0&fu=0&ifi=1&dtd=93" frameborder="0" width="728" allowtransparency="" name="google_ads_frame1" marginwidth="0" scrolling="no">
查看评论
7楼 fengjuyixuan 2012-06-10 18:11发表 [回复]
不错 刚好正在学习
6楼 hufeikong 2011-06-06 00:01发表 [回复]
文章不错,就是对照不能成功!
关于&quot;YYLEXERNAME&quot;这个错误相信所有按照这步骤操作的人都遇到了.
5楼 chouchou2007 2010-03-09 13:59发表 [回复]
你好,请教下如果我想在64位Windows7下使用该词法分析工具,应该怎么配置,能在64位环境下使用吗
4楼 everyhook 2010-01-07 19:43发表 [回复]
但貌似你已经不在了,你的最后文章是在08年。
3楼 everyhook 2010-01-07 19:42发表 [回复]
你好,可以回答一下吗???
太可惜了,你是两年前写的文章。
我的编译器不能编译成功。
单独编译 *.l 或 *.y都可以 ,但是合起来就不可以。
很希望你还在csdn上。
2楼 霸天Dana 2009-08-17 09:58发表 [回复]
呵呵,我自己已经明白了.多谢
1楼 霸天Dana 2009-08-17 09:55发表 [回复]
之后在vc6.0加入如下设置

Tool-&gt;Option-&gt; directory

Bin file :???

你好,请问为什么我找不到这个项目栏呢?
我本地显示的是
Tools-&gt;Options-&gt; directories,其中显示了以下三个属性
Platform;Show directories for;directories
发表评论
  • 用 户 名:
  • xizmi
  •   
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
TOP
  • 个人资料
    • 访问:28104次
    • 积分:416分
    • 排名:千里之外
    • 原创:11篇
    • 转载:3篇
    • 译文:1篇
    • 评论:13条
  • 推荐文章
    • 最新评论
    公司简介| 招贤纳士| 广告服务| 银行汇款帐号| 联系方式| 版权声明| 法律顾问| 问题报告
    QQ客服 微博客服 论坛反馈 服务热线:400-600-2320
    京 ICP 证 070598 号
    北京创新乐知信息技术有限公司 版权所有
    江苏乐知网络技术有限公司 提供商务支持
    Copyright © 1999-2014, CSDN.NET, All Rights Reserved  GongshangLogo
    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值