最近写了一点儿 D 程序,除了感觉标准库太差之外,没有一个好的 IDE 也是一个很头疼的事,特别是没有智能提示,每次调用一个函数什么的,都要查文档或者直接看源代码,实在是太费劲了。
所以决定自己尝试写一个支持智能提示的 D 的 IDE。因为 SharpDelelop 比较小,而且它对 C# 的支持也做到了智能提示、窗体编辑器等等,所以决定用它作为主框架,除了智能提示,也许还能加入 DFL 的窗体编辑之类的功能(Entice 做的窗体编辑已经不错了,只是没有事件支持)。目前,已经完成了语法加亮,代码折叠(目前和 notepad++ 一样只是通过大括号匹配来做的),下一步,就是智能提示了,而智能提示就牵涉到语法分析。
找了几个分析器生成器,试用之后,觉得 Grammatica 还不错,生成的代码比较清晰,调试起来也比较方便。照它的例子写了一个四则运算的分析器,还不错。
看了一下 D 的语法详细列表,那也不是一般的复杂。所以,决定先写一个简单的语言的分析器、编译器和虚拟机练练手。今天先把虚拟机做了出来。
这种语言的语法非常简单,姑且称之为 Z 语言吧(还没有细化):
声明语句: int x; // 只支持 int
赋值语句: x = 1;
条件语句: if(x > 1) { ... } else { ... }
跳转语句: goto lable
标签语句: :lable
输出语句: write(x); // 只支持 int
注释语句: // ... <eol>
而虚拟机部分,参照 x86 asm,定义如下:
寄存器: EAX, EBX, ESP, EIP // EAX,EBX操作数,ESP堆栈指针,EIP指令指针
内存: 200000B,0B~99999B为堆栈,100000B~199999B为程序
指令:
为EAX赋值: set eax, 1 // 01 01 00 00 00
将当前堆栈地址变量复制到eax: mov eax, *esp // 02
为EAX赋值: set ebx, 1 // 03 01 00 00 00
将当前堆栈地址变量复制到ebx: mov ebx, *esp // 04
为当前堆栈地址变量赋值eax: mov *esp, eax // 05
为当前堆栈地址变量赋值ebx: mov *esp, ebx // 06
esp 加运算: add esp, 1 // 07 01 00 00 00
eax 加运算: add eax, ebx // 08
eax大于ebx?结果放eax: gt // 11
eax大于等于ebx?结果放eax: gteq // 12
eax等于ebx?结果放eax: eq // 13
eax bool not: not // 14
eax 为非 0 跳转(相对): if eax jmp {sp} // 21 {sp}
无条件跳转(相对): jmb {sp} // 22 {sp}
输出 eax: out // 31
结束: over // ff
另外,虚拟机需要能显示寄存器值,显示当前堆栈顶值,显示输出。支持单步执行。
再写一段小程序,用来验证虚拟机的运行情况,因为只支持 int,所以计算 1 到 100 的和是一个比较合适的小代码段, C 的代码如下:
int n = 0;
for(int i=1; i<=100; i++)
{
n += i;
}
write(n);
Z 语言不支持 for 循环,所以,相应的 Z 代码大体如下:
int n = 0;
int i = 1;
:next
if(i > 100) { goto end; }
n += i;
i++;
goto next;
:end
write(n);
而根据上面定义的指令集,其相应的汇编代码如下:
// esp n, esp+4 i;
// int n = 0;
set eax, 0 // 01 00 00 00 00
mov *esp, eax // 05
// int i = 1;
add esp, 4 // 07 04 00 00 00
set eax, 1 // 01 01 00 00 00
mov *esp, eax // 05
// :next
// if(i > 100) { goto end; }
mov eax, *esp // 02
set ebx, 100 // 03 64 00 00 00
gt // 11
if eax jmb <end> // 21 1B 00 00 00
// n += i;
mov ebx *esp // 04
add esp, -4 // 07 FC FF FF FF
mov eax *esp // 02
add eax, ebx // 08
mov *esp, eax // 05
add esp, 4 // 07 04 00 00 00
// i++;
mov eax, *esp // 02
set ebx, 1 // 03 01 00 00 00
add eax, ebx // 08
mov *esp, eax // 05
// goto next;
jmb <next> // 22 D9 FF FF FF
// :end
// write(n);
add esp, -4 // 07 FC FF FF FF
mov eax, *esp // 02
out // 31
over // FF
虚拟机的代码不算复杂,VM 类拥有 eax, ebx, esp, eip 等属性,然后有一个函数 Step 提供执行一条指令的功能,在 Step 中,使用一个 switch 来处理不同的指令。之后,运行程序,把上面的汇编代码的字节序列写入 add.bin 文件中,用虚拟机加载,运行,得到结果:5050。
在把 Z 转换到汇编的过程中,发现写编译器的话,对于寄存器的使用,是一个很需要考虑的问题,而对于 D 智能提示,只需要分析器就够了,似乎写编译器有一些超出了,不过,既然都写了,就试着先把这个完成吧。
下面是源代码和运行截图:
- 描述: 运行截图
- 大小: 12.7 KB
分享到:
相关推荐
ua-parser-1.3.0
下载 ua-parser-master cd /app/ua-parser-master/java vi pom.xml <version>1.3.0</version> 原来是<version>1.3.1-SNAPSHOT mvn package -DskipTests mvn install:install-file -Dfile="/app/ua-parser-master/...
ua-parser-1.3.0.jar,现在maven中http://maven.twttr.com/ua_parser/ua-parser/1.3.0/ua-parser-1.3.0.pom下载不下来。
JavaParser 不仅仅是一个简单的语法解析器,它是一个完整的工具链,包括词法分析、语法分析、抽象语法树(AST)的构建以及对AST的遍历和修改。它支持Java语言的最新版本,可以处理现代Java代码的各种复杂特性。 这...
JavaParser:访问 该项目包含上书籍的代码示例 标题 JavaParser:已访问 作者 尼古拉斯·史密斯(Nicholas Smith),丹尼·范·布鲁根(Danny van Bruggen)和费德里科·托马塞蒂(Federico Tomassetti) 前导文字 ...
SGML::Parser::OpenSP 是一个Perl模块,它提供了一个用C++和XS编写的本地Perl接口,用于访问OpenSP(Open Source Parser)的SGML(Standard Generalized Markup Language)和XML(eXtensible Markup Language)解析...
mp4parser中的视频处理方法需要依靠该jar包才能运行,该jar包是基于mp4parser-mp4parser-project-1.9.27打包的。使用方法可以参考我的CSDN博文,地址是http://blog.csdn.net/u014691453/article/details/53256605
《视频编辑MP4 Parser代码与jar包》 ...总的来说,MP4 Parser是一个强大的工具,对于需要处理MP4文件的开发者来说,它是不可或缺的资源。通过深入理解和实践提供的示例代码,你将能够自如地应对各种视频编辑任务。
`pull-parser-2.jar`工具类库就是这样一个专门针对XML和JSON解析的利器,它为开发者提供了便捷、高效的解析方式,极大地优化了数据处理的流程。 XML(Extensible Markup Language)和JSON(JavaScript Object ...
你可以创建一个`Item`类,然后在`parser(_:didStartElement:namespaceURI:qualifiedName:attributes:)`中开始创建新的`Item`实例,在`parser(_:foundCharacters:)`中收集属性值,并在`parser(_:didEndElement:...
Parser :: Combinators是一个解析器构件块(“ parser combinators”)库,其灵感来自Haskell( )中的Parsec解析器组合库。 。 这个想法是,您不是通过指定语法(例如yacc / lex或Parse :: RecDescent)来构建解析...
本示例"IOS开发 XmlParser Demo"提供了一个简单的教程,帮助开发者理解如何在Xcode 4.2环境下集成并使用XMLParser。 首先,让我们了解XMLParser的基本工作原理。XMLParser遵循SAX(Simple API for XML)解析模式,...
`arg_parser`是一个用于解析命令行参数的C++库,同时也支持C语言接口。这个库在软件开发中扮演着重要角色,特别是在需要通过命令行接口与用户交互的工具或服务中。下面我们将深入探讨`arg_parser`的核心概念、功能、...
Parser_Generator是一个在Windows操作系统环境下使用的工具,主要用于生成解析器(Parser)和生成器(Generator)。解析器是计算机科学中的一个重要组件,它处理输入源代码,将其转化为抽象语法树(AST),这是理解...
快速开始首先,将其添加到您的Cargo.toml : [ dependencies ]conch-parser = " 0.1.0 " 接下来,您可以开始: use conch_parser :: lexer :: Lexer;use conch_parser :: parse :: DefaultParser;fn main () { // ...
:red_heart: 简单PHP代码解析器 您可以简单地扫描字符串,文件或完整目录,并且可以从php代码中看到简单的数据结构。 类( PHPClass ) 属性( PHPProperties ) 常量( PHPConst ) 方法( PHPMethod ) 接口...