我们现在已经可以写好文法了,下一步我们打算开始正式创建工程了
在工程目录下,我们创建如下文件夹
1
2
3./include ./memory ./ms
include
文件夹下我们将放头文件
memory
是内存管理模块,检测内存泄漏
ms
文件夹主要是放源文件
memory内存管理模块可以参考我另一个随笔 https://www.cnblogs.com/stdpain/p/10484403.html ,不愿意了解的话直接把里面的函数当做malloc
,free
即可
我们先创建lex文件ms.l
这个是flex使用的文件,下面是部分代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20%{ #include <stdio.h> #include <string.h> #include "../include/create.h" #include "y.tab.h" /* 一个功能性函数-都要加 */ int yywrap(void) { return 1; } %} %start COMMENT STRING_LITERAL_STATE %% <INITIAL>"function" return FUNCTION; <INITIAL>[A-Za-z_][A-Za-z_0-9]* { yylval.identifier = Interpreter_str_malloc(yytext); return IDENTIFIER; }
%{
中的内容会被原封不动的输出到文件中,%%
之后是正则表达式匹配然后返回某个token(终结符),将会被bison识别,<...>
前缀代表状态的意思,因为正则表达式有时候有一定的局限性(贪心匹配)
{}
中的内容可以使用我们定义好的函数,当成功匹配的时候会执行里面的函数,return 也是返回某个token,yylval是yacc内置的对象,我们可以让yylval保存一些变量
我们接着编写其他的正则表达式
1
2
3
4
5
6
7
8
9
10
11
12<INITIAL>([1-9][0-9]*)|"0" { int temp; sscanf(yytext, "%d", &temp); yylval.integer = temp; return INT_LITERAL; } <INITIAL>[0-9]+.[0-9]+ { double temp; sscanf(yytext, "%lf", &temp); yylval.db = temp; return DOUBLE_LITERAL; }
以上两个分别是整数和浮点数的正则表达式,通过scanf读取然后保存到yylval中
1
2
3
4<INITIAL>" { open_charbuffer(); BEGIN STRING_LITERAL_STATE; }
当遇见"
的时候说明遇到了字符串,这个时候很多规则都会变动,我们可以让他转换到另一个状态 BEGIN 后面就是状态的名字, open_charbuffer()是我们写的函数用于打开一个缓冲区存放字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<STRING_LITERAL_STATE>" { yylval.identifier = flush_charbuffer(); BEGIN INITIAL; return STRING_LITERAL; } <STRING_LITERAL_STATE>n { addc_charbuffer('n'); } <STRING_LITERAL_STATE>\" addc_charbuffer('"'); <STRING_LITERAL_STATE>\n addc_charbuffer('n'); <STRING_LITERAL_STATE>\t addc_charbuffer('t'); <STRING_LITERAL_STATE>\\ addc_charbuffer('\'); <STRING_LITERAL_STATE>. addc_charbuffer(yytext[0]);
在字符串模式下,我们可以在遇到各种字符的时候可以添加到缓冲区,注意特殊字符需要转义,再次遇到"
的时候把缓冲区刷新然后保存这个字符串到yylval中并且转移到初始模式
1
2
3
4
5
6
7
8
9
10
11
12
13<INITIAL>. { //error char buf[1024]; if (isprint(yytext[0])) { buf[0] = yytext[0]; buf[1] = ''; } else { sprintf(buf, "0x%02x", (unsigned char)yytext[0]); } printf("meet:%s",buf); abort(); }
遇到期望之外的字符直接错误处理即可,
这几个字符串缓冲区函数我们先简单实现一下即可,有较长字符串需求的时候再重新写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18void open_charbuffer() { buffer = Interpreter_malloc(100); pos = 0; } void addc_charbuffer(char c) { assert(buffer); assert(pos < 100); buffer[pos++] = c; } char *flush_charbuffer() { char *p = buffer; buffer[pos] = 0; buffer = NULL; return p; }
代码已经上传至github
地址:https://github.com/stdpain/compiler-interpreter
其中ms.l在ms/ms.l
转载于:https://www.cnblogs.com/stdpain/p/10528826.html
最后
以上就是快乐小蚂蚁最近收集整理的关于使用bison和yacc制作脚本语言(3)的全部内容,更多相关使用bison和yacc制作脚本语言(3)内容请搜索靠谱客的其他文章。
发表评论 取消回复