lex和yacc环境配置

lex和yacc的使用很简单,但环境配置却是各种问题,本章说明lex和yacc在windows下的环境配置。

软件需求:
系统 win7-64位(win7-32, win8, win10全部通过)
c++编译器: vs2010(2008,2013,2015也全部通过)
lex和yacc编译器: ParGen.exe

基本流程:
安装Pargen.exe,采用的默认目录安装在C:\Program Files (x86)\Parser Generator 2\
安装vs2010,这个各种教程,不再赘述

启动Pargen程序,并选择Project->ParserWizard…
这里写图片描述

选中ParserWizard,开始工程的创建,此处我创建功能,命名为Test,目录位置可自己选择,目标语言为C++,编译器为vc++(32-bit)
这里写图片描述

下一步,选择是创建lex,还是yacc,还是两者兼有。此处我选择是lex和yacc都有,准备实现一个不支持变量的计算器,使用lex识别token,使用yacc识别语法。
这里写图片描述

下一步,设置yacc的文件名字以及使用的解析器,此处我使用的默认选项,不进行修改,文件名默认为myparser.y
这里写图片描述

下一步,设置lex的文件名以及使用的分析器的名字,此处我使用的默认选项,文件名默认为mylexer.l
这里写图片描述

点击完成按钮,创建工程完毕,同时有两个文件mylexer.l 和myparser.y
这里写图片描述

工程的管理,可使用window->project菜单,查看工程下的所有文件
这里写图片描述
这里写图片描述

当你点击文件编辑窗口的放大按钮,会将其他的文件编辑覆盖,此时可以使用window->project菜单查看,也可以使用window->Tile vertically查看全部文件的平铺
这里写图片描述

编辑mylexer.l文件,粘贴入以下内容:

%{
//this code will be added into the header of generated .cpp file
#include <iostream>
#include "myparser.h"
using namespace std;//already defined in yacc.y, use %token...
//enum{LT,  EQ, GT, IF, ELSE, ID, NUMBER, PLUS, MINUS, TIMES, OVER, INT, DOUBLE,CHAR, LP,RP};const char* tokenStr[] = {"LT",  "EQ", "GT", "IF", "ELSE", "ID", "NUMBER", "PLUS", "MINUS", "TIMES", "OVER", "INT", "DOUBLE","CHAR"};
static void print_token(int token, char* lex);%}%name mylexerdelim [ \t]
ws    {delim}+
letter [a-zA-Z]
digit [0-9]
id    {letter}({letter}|{digit})*
/* can support 12.34 */
number {digit}+(\.{digit}+)?%%
%{
//this code will be added into yyaction functionYYSTYPE YYFAR& yylval = *(YYSTYPE YYFAR*)yyparserptr->yylvalptr;//double yylval;
%}{ws} {/* do nothing */}
"int"  {print_token(INT, yytext); return INT;}
"double"  {print_token(DOUBLE, yytext);}
"char"  {print_token(CHAR, yytext);}"+"         {print_token(PLUS, yytext); return PLUS;}
"-"         {print_token(MINUS, yytext); return MINUS;}
"*"         {print_token(TIMES, yytext); return TIMES;}
"/"         {print_token(OVER, yytext); return OVER;}
"("         {return LP;}
")"         {return RP;}
"\n"        {return EOL;}
{id}        { return ID;}
{number}    { yylval = atof(yytext);return NUMBER;}
"//".*      {return COMMENT;}
"."          {printf("Mystery character %s\n", yytext); }
%%static void print_token(int token, char* lex)
{
#ifdef LEX_DEUBcout<<"token:" << token<<" "<<"lex:"<<lex<<endl;
#endif
}

编译myparser.y文件,粘贴入以下内容

%{
#include "mylexer.h"
%}%name myparser
// class definition
{// place any extra class members here
}
// constructor
{// place any extra initialisation code here
}// destructor
{// place any extra cleanup code here
}// place any declarations here
%include {
#ifndef YYSTYPE
#define YYSTYPE double
#endif
}%token NUMBER ID
%token PLUS MINUS TIMES OVER
%token LP RP EOL COMMENT
%TOKEN INT DOUBLE CHAR%left PLUS MINUS
%left TIMES OVER
%right UMINUS%%lines   :   lines expr EOL  { printf("%g\n", $2); }|   lines EOL|  lines COMMENT|;expr    :   expr PLUS expr  { $$ = $1 + $3; }|	expr MINUS expr	{ $$ = $1 - $3; }|	expr TIMES expr	{ $$ = $1 * $3; }|	expr OVER expr	{ $$ = $1 / $3; }|	LP expr RP	{ $$ = $2; }|	'-' expr %prec UMINUS	{ $$ = -$2; }|	NUMBER {$$=$1;} //$$=$1 can be ignored|   ID //should be complemented;  
%%int main(int argc, char *argv[])
{printf("a cacluator which support +,-,*,/ and (): \n");printf("    e.g.  12.2+3*(2+5)\n");int n = 1;mylexer lexer;myparser parser;if (parser.yycreate(&lexer)) {if (lexer.yycreate(&parser)) {//lexer.yyin = new ifstream(argv[1]);//lexer.yyout = new ofstream(argv[2]);n = parser.yyparse();//parse_tree.get_label();//parse_tree.gen_code(*lexer.yyout);}}getchar();return n;
}

点击Pargen右上角的编译build按钮,会生成相应的.h和.cpp代码
这里写图片描述
这里写图片描述

新建vs2010工程,并将生成的.h和.cpp代码加入到工程中。简单起见,在comple\Test目录下创建vs工程vsTest
这里写图片描述

选择控制台工程, 工程的目录,以及工程名称vsTest,点击确定按钮后
这里写图片描述

继续下一步配置
这里写图片描述

此处附件选项选择空项目,然后点击完成按钮,即完成vsTest工程创建
这里写图片描述

工程右键添加现有项,即添加已经生成.h和.cpp文件
这里写图片描述
这里写图片描述
这里写图片描述

在vs界面,点击编译按钮,查看当前的编译情况,会显示编译错误,找不到yy的头文件,这是因为并没有将Pargen安装后的头文件加入到工程的包含目录中
这里写图片描述

下面将Pargen安装后的头文件加入到工程include配置
这里写图片描述
这里写图片描述
这里写图片描述

在vs界面,点击编译按钮,查看编译情况。 当前头文件可以正常找到,会出现大量的链接错误-link error。这是因为对应的lib文件还没有加载进来。
这里写图片描述

下面加入库文件,加入库所在目录
这里写图片描述

加入要使用的库的名字:ylmtri.lib, 注意使用分号隔开
这里写图片描述

再次点击编译按钮,会发现可以编译,但是运行的时候,会出现ylmtri.dll的错误。这是因为我们使用动态dll库,需要将对应的dll文件从Pargen目录复制到工程目录的exe文件同级目录下
这里写图片描述

下面开始将ylmtri.dll从Pargen目录复制到vsTest.exe同级目录
这里写图片描述
这里写图片描述

再次点击编译运行按钮,可以正常运行,效果如下
这里写图片描述
这里写图片描述



出处:http://blog.csdn.net/lpstudy/article/details/51330063


在最后一步的过程中,遇到了添加完ylmtri.dll仍然报错的情况,也是比较尴尬,在解决之后再修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508605.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java集合之Vector源码分析

概述 Vector与ArrayLIst类似, 内部同样维护一个数组, Vector是线程安全的. 方法与ArrayList大体一致, 只是加上 synchronized 关键字, 保证线程安全, 下面就不具体分析源码了, 具体可以查看ArrayList中的源码分析. Vector源码分析 1.主要字段 2.构造函数 3.增删改查 其他方法…

Gossip协议的P2P会员管理

阅读此论文主要目的在于理解gossip协议及其背后的原理&#xff0c;此部分详细翻译&#xff0c;其余部分看时间 文章标题&#xff1a;Gossip协议的P2P会员管理 作者&#xff1a;Ayalvadi J. Ganesh, Anne-Marie Kermarrec, and Laurent Massoulie Abstract&#xff1a;基于…

Java集合之LinkedHashSet源码分析

概述 LinkedHashSet与HashSet类似, 不同的是LinkedHashSet底层使用LinkedHashMap维护元素插入的顺序. LinkedHashSet继承自HashSet, 只是重写了HashSet的构造方法, 初始化一个LinkedHashMap, 其他均与HashSet相同. LinkedHashSet构造方法 HashSet的构造方法: 以上几乎就是Li…

Java集合之ArrayList源码分析

概述 ArrayList可以理解为动态数组, 根据MSDN的说法, 就是Array的复杂版本. 与数组相比, 它的容量能动态增长. ArrayList是List接口的可变数组的实现. 实现了所有可选列表操作, 允许包括null在内的所有元素. 数组的特点, 查询快增删慢. 每个ArrayList实例都有一个容量, 该容…

Java集合之Hashtable源码分析

概述 Hashtable也是基于哈希表实现的, 与map相似, 不过Hashtable是线程安全的, Hashtable不允许 key或value为null. 成员变量 Hashtable的数据结构和HashMap一样, 采用 数组加链表的方式实现. 几个成员变量与HashMap一样: 方法 Hashtable的方法与HashMap基本一样, 只是 Ha…

视频质量检测中的TP、FP、Reacll、Precision

在看论文《Measuring Vedio QoE from Encrypted Traffic》的时候看到TP&#xff08;True Positives&#xff09;、FP&#xff08;False Positives&#xff09;、Precison、Recall的概念&#xff0c;这属于数据挖掘方面的内容&#xff0c;学习之后特来记录。 首先&#xff0c;下…

Java集合之LinkedHashMap源码分析

概述 HashMap是无序的, 即put的顺序与遍历顺序不保证一样. LinkedHashMap是HashMap的一个子类, 它通过重写父类的相关方法, 实现自己的功能. 它保留插入的顺序. 如果需要输出和输入顺序相同时, 就选用此类. LinkedHashMap原理 LinkedHashMap是如何保证输入输出顺序的呢? L…

Java集合之HashSet源码分析

概述 HashSet是基于HashMap来实现的, 底层采用HashMap的key来保存数据, 借此实现元素不重复, 因此HashSet的实现比较简单, 基本上的都是直接调用底层HashMap的相关方法来完成. HashSet的构造方法就是创建HashMap: 基本操作 1.添加操作 2.删除操作 3.迭代器 其他方法基本也是调…

三次握手wireshark抓包分析,成功握手和失败握手

转载之前&#xff1a;基于HTTP的视频流中&#xff0c;客户端有时会打开使用多条TCP与服务器连接&#xff0c;为了验证每一对话的sessionID是否相同&#xff0c;使用wireshark进行了抓包分析&#xff08;抓到的都是加密的包&#xff0c;无卵用orz....&#xff09;&#xff0c;这…

Java 内部类及其原理

Java中实现内部类 内部类相信大家都用过很多次了&#xff0c;就不说它是怎么用的了。 内部类 1.成员内部类 需要注意的是&#xff0c; 当成员内部类拥有和外部类同名的成员变量或这方法时&#xff0c; 默认情况下访问的是内部类的成员&#xff0c; 如要访问外部类的同名成员&…

Java8 Lambda表达式

概述 lambda表达式&#xff0c; 是Java8中的一个新特性。可以理解为一个匿名函数。 lambda表达式可以理解为将一个函数浓缩为一行代码&#xff0c;使代码更加简洁紧凑。 lambda表达式语法&#xff1a; (parameters) -> statement; 或 (parameters) -> {statements;} 参…

Java8 方法引用

概述 方法引用是用来直接访问类或实例阴茎存在的方法或者构造方法.它需要由兼容的函数式接口(lambda表达式中用到的接口)构成的目标类型上下文. 有时候, 当我们想要实现一个函数式接口的方法, 但是已经由类实现了我们想要的功能, 这时可以使用方法引用来直接使用现有的功能实现…

配置过程中的一些问题

一、 Tomcat相关问题 1、百度经验有设置用户名密码&#xff0c;但是按照步骤进行&#xff0c;到测试的时候发现还是错误的。 解决&#xff1a;在设置的时候应该stop Tomcat&#xff0c;在设置好之后再重新开启Tomcat&#xff0c;发现可以。 2、把web项目加入Tomcat&#xff0…

流媒体通信协议HLS与DASH的对比

简单了解 HLS(HTTP Live Streaming)协议 是由苹果公司实现的基于HTTP的流媒体通信协议&#xff0c;并成为Quick TIme X和IPhone软件系统的一部分。苹果的IPad也有支持HLS的能力。 HLS传出的视频文件为基于MPEG2文件的切片&#xff0c;每个媒体切片在服务器上单独存放。在一个流…

Activity的四种启动模式和onNewIntent()

Android中Activity启动模式详解 在Android中每个界面都是一个Activity&#xff0c;切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。 Android总Activity的启动模式分为四种&#xff1a; Activity启动模式设置…

Java8 默认方法

概述 Java8新增了接口的默认方法。使用default关键字。 默认方法就是接口可以有实现方法&#xff0c;而且不需要实现类来实现其方法。相对于JDK1.8之前的接口来说&#xff0c;新增了可以接口中实现方法。 可以说在接口中实现方法一部分原因是为了lambda表达式服务的&#xf…

Android Activity 生命周期中onStart()和onResume()的区别

首先了解Activity的四种状态 Running状态&#xff1a;一个新的Activity启动入栈后&#xff0c;它在屏幕最前端&#xff0c;处于栈的最顶端&#xff0c;此时它处于可见并可和用户交互的激活状态。 Paused状态&#xff1a;当Activity被另一个透明或者Dialog样式的Activity覆盖时的…

Android 原生ExoPlayer 解析

1.简述与应用范围 ExpPlayer是一个开源的&#xff0c;App等级的媒体API&#xff0c;它的开源项目包含了library和示例。 ExoPlayer相较于MediaPlayer有很多优点&#xff1a; 1. 支持基于http的移动流媒体协议&#xff0c;包括DASH&#xff0c;HSL&#xff0c;Smooth Stream。同…

Java8 Stream

概述 Java8 API中添加了一个新的抽象成为流Stream&#xff0c;可以以一种声明的方式处理数据。 Stream与java.io包中的InputStream和OutputStream是完全不同的概念。Java8中的Stream是对集合对象功能的增强&#xff0c;专注与对集合对象进行各种非常便利、高效的聚合操作&…

Java 注解原理

下面来看看Java中注解是如何实现的 创建注解类Inter: 创建测试类Test: 在程序第二句设置断点,可以看到: 可以看到,注解的实例是一个动态代理类的对象. 要想查看这个动态代理类,可以在代码中加 System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", …