自己去创建一个编程语言吧(2)

上一节中,你已经定义好了语言风格,和关键字、运算符。

现在就可以开始编写代码了。

编写代码的主要作用是分析源代码,分析其中的逻辑,按照你定义的逻辑方法进行执行,分析过程,比较复杂,

所以,要采用工具简化分析过程

首先要下载Win flex-bison,下载地址
https://sourceforge.net/projects/winflexbison/

下载解压后,直接解压,大概的文件如下图
在这里插入图片描述
可能你下载到的版本不同,但这都不重要,你只需要关注

win_flex.exe,win_bison.exe就可以

1.词法分析
常用词法分析的工具是FLEX,他可以按照你定义的正则表达式对源代码进行分析,从中提取你想要的信息.看一个简单的例子,来说明flex的文件结构

%{
#include <iostream>
  int lines = 0;
  int words = 0;
  int chars = 0;
%}    
%%
[a-zA-Z]+       { ++words; chars += strlen(yytext); }
"\n"          { ++lines; ++chars; }
.             { chars += strlen(yytext); }
%%
int yywrap() { return 1; }

flex的文件,通常以.l结尾,flex被执行后,将变为c源文件,通常文件名为lex.yy.c

flex程序分为三个段:定义段、规则段、用户子程序段
/* 定义段 */
%{
...
%}
...

%%
    /* 规则段 */
...
%%

    /* 用户子程序段 */
...

三个段用%%进行分隔
1.定义段

这一部分一般是一些声明及选项设置等。C语言的注释、头文件包含等一般就放在%{%}之间,这一部分的内容会被直接复制到输出文件的开头部分.

2.规则段

规则段为一系列匹配模式和动作,模式一般使用正则表达式书写,动作部分为C代码: 模式1 {动作1 (C代码)}
在输入和模式1匹配的时候,执行动作部分的代码。

3.用户子程序段

这里为C代码,会被原样复制到输出文件中,一般这里定义一些辅助函数等,如动作代码中使用到的辅助函数。
词法分析器所做的,就是在输入中寻找字符的模式(pattern)。在词法分析器中,我们要给定我们需要识别的模式,因此需要使用一种方式来描述模式,这就是常用的正则表达式。学习正则表达式

在上例中,

%{
#include <iostream>
  int lines = 0;
  int words = 0;
  int chars = 0;
%}

会被原模原样的复制到lex.yy.c中

%%
[a-zA-Z]+     { ++words; chars += strlen(yytext); }
"\n"          { ++lines; ++chars; }
.             { chars += strlen(yytext); }
%%

作为规则,会被解析,你输入的内容,会被felx程序分析,例如正则表达式[a-zA-Z]+,是分析输入的字符串的,分析到以后{}中的程序就会执行,yytext就是你输入的字符串

int yywrap() { return 1; }

本段,也是用户自定义的程序,同样和第一段一样,会被原模原样的复制到lex.yy.c中

如果要让,上面程序可以执行,还差一个main

int main()
{
    yylex();
}

现在完整执行一下

如果执行成功,则在工作目录中会产生lex.yy.c

现在,在VS中,新建一个项目,把这文件放进去,编译运行

如果你是在VS中执行,可能会报错,,将lex.yy.c,改名为lex.yy.cpp,在执行,如果遇到无法打开unistd.h的情况,你可以自己创建一个,内容如下

#ifndef _UNISTD_H
#define _UNISTD_H
#include <io.h>
#include <process.h>
#endif /* _UNISTD_H */

不知道你到底弄明白没有,没关系,关于flex的更多信息,你可以去看看这个地址
http://dinosaur.compilertools.net/flex/index.html
如果看完还不明白…

那就接着看下面吧

现在,看一下在Menthol中关于关键字和运算符,还有标识符的定义。我截取一部分来测试

%{
#include <iostream>
static void echo(char* str,char* keywordstr);
int keyword = 0;
%}    
%%

"if"        {echo("keyword","if");}
"else"      {echo("keyword","else");}
"for"       {echo("keyword","for");}
"break"       {echo("keyword","break");}
"true"        {echo("keyword","true");}
"false"       {echo("keyword","false");}
"try"         {echo("keyword","try");}
"except"      {echo("keyword","except");}
"throw"       {echo("keyword","throw");}
"continue"    {echo("keyword","continue");}
"return"      {echo("keyword","return");}
"while"       {echo("keyword","while");}
"null"        {echo("keyword","null");}
"import"        {echo("keyword","import");}
"_mmain"    {echo("keyword","_mmain");}
"def"     {echo("keyword","def");}
"var"     {echo("keyword","var");}
"in"            {echo("keyword","in");} 
"typeof"        {echo("keyword","typeof");}
"module"        {echo("keyword","module");}
"use"           {echo("keyword","use");}
"const"         {echo("keyword","const");}
"+"       {echo("operator","+");}
"-"       {echo("operator","-");}
"*"       {echo("operator","*");}
"/"       {echo("operator","/");}
"{"         {echo("operator","{");}
"}"         {echo("operator","}");}
"("         {echo("operator","(");}
")"         {echo("operator",")");}
";"       {echo("operator",";");}
"|"         {echo("operator","|");}
"&"       {echo("operator","&");}
","       {echo("operator",",");}
"?"       {echo("operator","?");}
"."       {echo("operator",".");}
"["       {echo("operator","[");}
"]"       {echo("operator","]");}
"!"       {echo("operator","!");}
"%"       {echo("operator","%");}
"^"       {echo("operator","^");}
":"       {echo("operator",":");}
"::"      {echo("operator","::");}


"$"[a-zA-Z_][a-zA-Z_0-9]* {
              
              echo("local variable",yytext);
              
            }

"@"[a-zA-Z_][a-zA-Z_0-9]* {
              echo("global variable",yytext);
            }

[a-zA-Z_][a-zA-Z_0-9]* {
              echo("inentifier",yytext);
            }

[ \t]     /* ignore white space */
.             return yytext[0];


%%
static void echo(char* str,char* keywordstr)
{
  keyword++;
  printf("%s,%s,keywords=%d\r\n",str,keywordstr,keyword);
}

int yywrap() { return 1; }

int main()
{
    yylex();
    return 1;
}

翻译,编译,运行,看下图。

在这里插入图片描述

你现在应该明白flex该怎么用了吧

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值