我正在编写一个编译器(更多的是为了娱乐而不是其他任何东西),但我想尽量使它尽可能高效.例如,有人告诉我,在英特尔架构中,使用除EAX执行数学之外的任何寄存器都会产生成本(大概是因为它转换成EAX实际的数学运算).这里至少有一个说明可能性的来源(http://www.swansontec.com/sregisters.html).
我想验证和衡量这些性能特征的差异.因此,我用C++编写了这个程序:
#include "stdafx.h"
#include <intrin.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
__int64 startval;
__int64 stopval;
unsigned int value; // Keep the value to keep from it being optomized out
startval = __rdtsc(); // Get the CPU Tick Counter using assembly RDTSC opcode
// Simple Math: a = (a << 3) + 0x0054E9
_asm {
mov ebx, 0x1E532 // Seed
shl ebx, 3
add ebx, 0x0054E9
mov value, ebx
}
stopval …Run Code Online (Sandbox Code Playgroud) 编程语言似乎经历了几个阶段.首先,有人想出了一种新语言Foo Language.编译器/解释器是用另一种语言编写的,通常是C语言或其他一些低级语言.在某些时候,FooL会成熟并逐渐成长,最终某人会在FooL本身为FooL编写编译器和/或解释器.
我的问题是:语言功能的最小子集是什么,有人可以自己实现该语言?
我正在寻找能够用编程语言从输入程序创建Win32程序的编译器的源代码(哪个更好,也许更简单更好)
然而,我找不到任何适合我的东西,像GCC这样的大型编译器让我非常困惑,因为它们有很多功能,我不知道从哪里开始.
正如在删除左递归中所解释的,有两种方法可以删除左递归.
人们通常用什么来移除(没有)ANTLR的左递归?我使用flex/bison进行解析器,但我需要使用ANTLR.我唯一担心的是使用ANTLR(或普通的LL解析器)是去除递归.
我用以下语法做了一些实验.
E -> E + T|T T -> T * F|F F -> INT | ( E )
离开递归后,我得到以下一个
E -> TE' E' -> null | + TE' T -> FT' T' -> null | * FT'
我可以提出以下ANTLR表示.尽管如此,它相对简单明了,似乎没有左递归的语法应该是更好的方法.
grammar T;
options {
language=Python;
}
start returns [value]
: e {$value = $e.value};
e returns [value]
: t ep
{
$value = $t.value
if $ep.value != None:
$value += $ep.value
}
; … 我一直对编程/解释器设计/实现感兴趣,只要我编程(现在只有5年),它总是看起来像幕后的"魔术",没有人真正谈论过(我至少知道) 2个用于操作系统开发的论坛,但我不知道编译器/解释器/语言开发的任何社区).无论如何,最近我决定开始自己的工作,希望扩展我对整个编程的知识(嘿,这很有趣:).因此,基于我所拥有的有限数量的阅读材料和维基百科,我已经为编译器/解释器开发了这个组件的概念:
源代码 - >词法分析 - >抽象语法树 - >句法分析 - >语义分析 - >代码生成 - >可执行代码.
(我知道代码生成和可执行代码还有更多,但我还没有那么远:)
有了这些知识,我创建了一个非常基本的词法分析器(在Java中)从源文件中获取输入,并将标记输出到另一个文件中.示例输入/输出如下所示:
输入:
int a := 2
if(a = 3) then
print "Yay!"
endif
Run Code Online (Sandbox Code Playgroud)
输出(来自词法分析器):
INTEGER
A
ASSIGN
2
IF
L_PAR
A
COMP
3
R_PAR
THEN
PRINT
YAY!
ENDIF
Run Code Online (Sandbox Code Playgroud)
就个人而言,我认为从那里进行语法/语义分析,甚至可能甚至是代码生成都会非常容易,这让我有一个问题:为什么使用AST,当我的词法分析员看起来做得同样好的时候呢?但是,我用来研究这个主题的100%的资源似乎都坚持认为这是任何编译器/解释器的必要部分.我是否错过了AST的真正含义(显示程序逻辑流程的树)?
TL; DR:目前正在开发编译器,完成词法分析器,在我看来,输出将使得简单的句法分析/语义分析,而不是做AST.那为什么要用一个?我错过了一点吗?
谢谢!
我正在使用这个(见下文)算法(从这个答案的想法)到树的代码生成.我的目标是x86 arch,现在我需要处理使用寄存器eax/ebx作为参数的mul/div指令.
我的问题是:
如何修改它以加载某个指令的操作数以加载到固定寄存器?比如,对于mul指令加载左右子树eax和ebx寄存器.我当前的实现是:传递当前节点开始评估为参数,如果它是MUL或DIV设置reg为R0或R1根据树的一侧,如果它LEFT或RIGHT分别.如果reg是in_use,则推送reg堆栈并将其标记为开始免费(尚未实现).当前的实现不起作用,因为它assert(r1 != r2)在emit_load()函数中断言(意味着作为参数传递的两个寄存器都等于r1 = REG_R0和r2 = REG_R0)
void gen(AST *ast, RegSet in_use, AST *root) {
if(ast->left != 0 && ast->right != 0) {
Reg spill = NoRegister; /* no spill yet */
AST *do1st, *do2nd; /* what order to generate children …Run Code Online (Sandbox Code Playgroud) c compiler-construction algorithm code-generation compiler-theory
以下语言的最小抽水长度是多少?
(01)*10(11*0)*01011011 ü 0*1*这是我的解决方案.如果我错了,请纠正我.
01是可以泵送的最短字符串10100是可以泵送的最短字符串0可以泵送字符串我不确定我的答案,所以任何帮助都表示赞赏.非常感谢!
computer-science compiler-theory computation-theory regular-language
我很好奇哪些(如果有的话)现实世界的编程语言都有常规语法(即所有语法正确的程序集是常规的).
另请参阅此问题:哪些编程语言不受上下文限制?.
我正在编写一种语言解析器,扫描仪的设计目的是为了
基于布尔标志.
现在,在解析器中,我不想用所有这些终端混淆语法,它们应该被我正在构建的解析树以某种方式"自动地"吞噬.
要做到这一点"神奇",我想我会链接终端(简单地链接循环列表)所以我可以迭代它们并"填充空白",因为减少发生(我正在使用LALR(1)解析器生成器) .
这听起来像一个理智的想法,虽然有一个问题.记得我说"要么退还......要不"?在场景(2)中,我会释放终端,因为谁知道接下来会发生什么?而且我不希望任何内存泄漏.
但是在方案(1)中,我无法释放终端,因为基于它们,我将决定进一步减少哪些"填空"过程应该停止.
由于同样的原因,我无法有条件地释放它:我不知道接下来会发生什么.如果没有任何"填空"流程被触发怎么办?如果根本没有进一步减少怎么办?
你有类似的问题吗?你是怎么解决的?
注意:这完全在我的脑海中,我可能没有足够清楚地解释,请询问,我将编辑我的问题.这个场景实际上有点复杂,我不是从头开始写这个,我可以用我的想象力,我把它整合到其他东西中,所以很可能我会回答"我做不到因为环境的限制".
附录
我想到的唯一非常好的想法是分叉和改进解析器生成器,我已经在这里和那里的一些小地方做了,以克服我上面提到的一些限制.
我正在研究对应于大数学表达式(数百万个节点)的表达式图实现公共子表达式消除(CSE).
什么算法适合执行此操作?我在互联网上搜索一个易于实现的算法,但我找不到任何东西.如果可能,算法应该具有完整表达图的节点数的线性复杂度.
compiler-theory ×10
c ×2
algorithm ×1
antlr ×1
assembly ×1
c++ ×1
lalr ×1
open-source ×1
parsing ×1