小白说编译原理-6-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 mylexer

delim [ \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 function
    YYSTYPE 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_DEUB
    cout<<"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同级目录

再次点击编译运行按钮,可以正常运行,效果如下

终于完结了。

本人lpstudy 转载请注明出处:http://blog.csdn.net/lpstudy/article/details/51330063

时间: 2024-08-29 22:49:52

小白说编译原理-6-lex和yacc环境配置-多图的相关文章

小白说编译原理-5-变量支持计算器

简介 本章依然专注于使用yacc实现计算器,主要的特点是给算术运算增加变量支持. 模块拆分 它主要分为3个模块 1. lex词法分析器 2. yacc语法分析器 3. 符号表 功能描述 1. lex词法分析器 正规式的定义如下: delim [ \t] ws {delim}+ letter [a-zA-Z] digit [0-9] id {letter}({letter}|{digit})* /* can support 12.34 */ number {digit}+(\.{digit}+)?

小白说编译原理-9-最简单minus-c语言编译器

简介 继上节8说到利用手动构建的语法树解析下面的c语言代码: a = 1 sum = 0 input(x) while(a <= x){ sum = sum + a a = a+1; } print(sum) 而一个编译器不应该依赖用户去手动构建对应语言的语法树,我们需要的是一种支持自动构建语法树的策略.本节将要说明的就是如何利用前面1-6节学到的lex,yacc以及符号表,7-8节学到的语法树来支持给定c语言代码自动构建过程. 动机 在第5节变量支持的计算器中,对于expr的语法解析有如下的y

windows下Bullet 2.82编译安装(Bullet Physics开发环境配置)

平台:Win7,VS2010 1. Bullet库的组织 下图是Bullet_User_Manual中的截图: 从中可见,Bullet的LinearMath(线性数学模块),其上是BulletCollision(碰撞检测模块),然后BulletDynamics(刚体模拟模块)和BulletSoftBody(可变形体模拟模块)建立在BulletCollision之上,另外还有可选的导入导出插件和多线程模块.LinearMath.BulletCollision.BulletDynamics.Bull

拜小白教你OpenCV3.2.0+VS2017开发环境配置

第一部分:OpenCV3.2.0的下载 OpenCV官方下载地址: http://opencv.org/releases.html# 本人选择opencv3.2.0基于Windows平台.读者根据自己需要选择合适版本及平台下载. 下载完成后,双击进行解压  解压即是安装OpenCV库的过程,读者自己选择好安装路径 [建议]在英文路径下,不用有中文和空格  第二部分:配置Path系统环境变量 此电脑-右键"属性"-高级系统设置   找到Path进行编辑 把之前解压(安装)好的OpenCV

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一.实验要求 实验二 基于预測方法的语法分析程序的设计 一.实验目的 了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法. 二.实验内容 1.了解编译程序的基于预測方法的语法分析过程. 2.依据预測分析原理设计一个基于预測方法的语法分析程序. 三.实验要求 对给定文法G[S]: S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m 当中,$表示空串. 1.推断上

编译原理-NFA构造DFA

本题摘自北邮的编译原理与技术. 首先,根据此图构造状态转换表 表中第一列第一行表示从第一个符号B通过任意个空转换能到达的节点,Ia表示由此行的状态数组({B,5,1}可以看作0状态)经过一个a可以到达的节点,同理,Ib表示由状态数组经过一个b可以到达的节点. 当然,有些人可能觉得{B,5,1}和{5,1,3}看作两个状态不合理,他们之间不是有交集嘛,实际上他们之间并无交集,因为输入a后,{B,5,1}能到达的新节点是3,之所以要写成{5,1,3},可能是要兼顾逻辑吧>_> 再仔细观察第一行,既

编译原理-如何使用flex和yacc工具构造一个高级计算器

Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Scanner)的C源码. 扫描器是一种识别文本中的词汇模式的程序. 这些词汇模式(或者常规表达式)在一种特殊的句子结构中定义.一种匹配的常规表达式可能会包含相关的动作.这一动作可能还包括返回一个标记. 当 Lex 接收到文件或文本形式的输入时,它试图将文本与常规表达式进行匹配. 它一次读入一个输入字符,直到找到一个匹配的模式. 如果能够找到一个匹配的模式,Lex 就执行相关

编译原理(简单自动词法分析器LEX)

编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7%90%86%E7%AE%80%E5%8D%95LEX%EF%BC%88%E8%AF%8D%E6%B3%95%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90%E5%99%A8%EF%BC%89.zip

编译原理 - 实验四 - yacc基本使用(bison)

一.介绍 只要在Unix环境中写过程序,必定会邂逅神秘的Lex&YACC,就如GNU/Linux用户所熟知的Flex&Bison,这里的Flex就是由Vern Paxon实现的一个Lex,Bison则是GNU版本的YACC,在此我们将统一称呼这些程序为Lex和YACC,所以我们将用Flex和Bison来尝试下我们的实例. 二.准备工作(win7) ①  下载flex和bison并安装到D:\GnuWin32(尽量是根目录) ②    由于我们使用的flex和bison都是GNU的工具,所以