‘壹’ 在编译原理中: 文法S——>SS+|SS*|a能产生什么语言,并验证! 求高人指导!
为了使问题简化,我们考虑文法S->ss+|a,考虑s->ss*时,只要把+换成*即可。
0层递归是,s->a,文法的语言是{a}。是后缀表达式。
1层以内递归时,文法语言是{a,aa+}。是后缀表达式。
2层以内递归时,文法语言是{a,aa+}.{a,aa+}.{+}。其中.表示连接,是后缀表达式。
依此类推,多少层的递归都是后缀表达式。
把表达式的+换成*后依然为后缀表达式。
下面证明文法产生的语言是所有的以a为变量,以+和*为运算符的后缀表达式。
因为每个表达式都对应一个常规的表达式(如1*2+3就是常规表达式),下面只需证明语言能产生的后缀表达式对应所有的常规表达式。当常规表达式只有一个运算符,对应aa+或aa*。当常规表达式有两个运算符,可写成(表达式1).{+|*}.(表达式2),因为表达式1和2都只含一个运算符,所以可以用语言表示,上述常规表达式可用后缀表达式(表达式1).(表达式2).{+l*}表示。所以不管常规表达式有多少个运算符,都可以由语言的后缀表达式对应。
‘贰’ 编译原理问题
你是长春理工大学的吧?
前几天我们刚写完,一样的.
‘叁’ 编译原理词法分析程序
(一)Block子程序分析
procere enter(k: object1); //填写符号表
begin {enter object into table}
tx := tx + 1; //下标加1,tx的初始值为零,零下标不地址不填写标志符,用于查找失败使用
with table[tx] do //填入内容,保存标志符名和类型
begin name := id; kind := k;
case k of //根据类型判断是否正确
constant: begin if num > amax then //如果是常量,判断是否大于最大值,若是则报30号错
begin error(30); num :=0 end;
val := num //否则保存数值
end;
varible: begin level := lev; adr := dx; dx := dx + 1; //如果是变量,填写变量内部表示,LEVEl是变量的层次,adr为地址
end;
proc: level := lev //如果是过程,保存过程的层次
end
end
end {enter};
//查找符号表的位置
function position(id: alfa): integer;
var i: integer;
begin {find indentifier id in table} //从后向前查找
table[0].name := id; i := tx; //找到保存类型
while table[i].name <> id do i := i-1;
position := i //返回标志符在符号表中的位置
end {position};
procere block(lev,tx: integer; fsys: symset);
var dx: integer; {data allocation index} //数据分配索引
tx0: integer; {initial table index} //初始符号表索引
cx0: integer; {initial code index} //初始代码索引
procere enter(k: object1); //填写符号表,下次分析
begin {enter object into table}
tx := tx + 1;
with table[tx] do
begin name := id; kind := k;
case k of
constant: begin if num > amax then
begin error(30); num :=0 end;
val := num
end;
varible: begin level := lev; adr := dx; dx := dx + 1;
end;
proc: level := lev
end
end
end {enter};
function position(id: alfa): integer; //查找符号表,下次分析
var i: integer;
begin {find indentifier id in table}
table[0].name := id; i := tx;
while table[i].name <> id do i := i-1;
position := i
end {position};
procere constdeclaration; //常量声明
begin if sym = ident then //如果是标志符,读入一个TOKEN
begin getsym;
if sym in [eql, becomes] then //读入的是等号或符值号继续判断
begin if sym = becomes then error(1); //如果是“=”报1号错
getsym; //读入下一个TOKEN
if sym = number then //读入的是数字,填写符号表
begin enter(constant); getsym
end
else error(2) //如果不是数字,报2号错
end else error(3) //不是等号或符值号,报3号错
end else error(4) //如果不是标志符,报4号错
end {constdeclaration};
procere vardeclaration; //变量声明
begin if sym = ident then //读入的是标志符,填写符号表
begin enter(varible); getsym
end else error(4) //不是标志符,报4号错
end {vardeclaration};
procere listcode;
var i: integer;
begin {list code generated for this block}
for i := cx0 to cx-1 do
with code[i] do
writeln(i:5, mnemonic[f]:5, 1:3, a:5)
end {listcode};
procere statement(fsys: symset);
var i, cx1, cx2: integer;
procere expression(fsys: symset); //表达式分析
var addop: symbol;
procere term(fsys: symset); //项分析
var mulop: symbol;
procere factor(fsys: symset); //因子分析
var i: integer;
begin test(facbegsys, fsys, 24); //读入的是“(”,标志符或数字
while sym in facbegsys do
begin
if sym = ident then //是标志符,查表
begin i:= position(id);
if i = 0 then error(11) else //未找到,报11号错
with table[i] do //找到,读入标志符类型
case kind of
constant: gen(lit, 0, val); //写常量命令
varible: gen(lod, lev-level, adr);//写变量命令
proc: error(21) //过程名,报21号错
end;
getsym //读入下一个TOKEN
end else
if sym = number then //读入的是数字
begin if num > amax then //如果数字大于最大数,报30号错误
begin error(30); num := 0
end;
gen(lit, 0, num); getsym //调用数字命令,读入下一个TOKEN
end else
if sym = lparen then //读入的是“(”
begin getsym; expression([rparen]+fsys); //调用表达式分析函数
if sym = rparen then getsym else error(22) //如果“(”后无“)”,报22号错
end;
test(fsys, [lparen], 23)
end
end {factor};//因子分析结束
//项分析
begin {term} factor(fsys+[times, slash]); //调用因子分析程序
while sym in [times, slash] do //取得是乘、除号循环
begin mulop:=sym;getsym;factor(fsys+[times,slash]); //记录符号,调用因子分析
if mulop=times then gen(opr,0,4) else gen(opr,0,5) //写乘除指令
end
end {term};
begin {expression}
if sym in [plus, minus] then //如果是加减号
begin addop := sym; getsym; term(fsys+[plus,minus]); //记录符号,调用项分析程序
if addop = minus then gen(opr, 0,1) //写加减指令
end else term(fsys+[plus, minus]);
while sym in [plus, minus] do //如果是加减号循环
begin addop := sym; getsym; term(fsys+[plus,minus]);
if addop=plus then gen(opr,0,2) else gen(opr,0,3)
end
end {expression};
//条件过程
procere condition(fsys: symset);
var relop: symbol;
begin
if sym = oddsym then //如果是判奇符
begin getsym; expression(fsys); gen(opr, 0, 6) //取下一个TOKEN,调用expression,填指令
end else
begin expression([eql, neq, lss, gtr, leq, geq]+fsys);
if not(sym in [eql, neq, lss, leq, gtr, geq]) then //如果不是取到逻辑判断符号,出错.20
error(20) else
begin relop := sym; getsym; expression(fsys);
case relop of
eql: gen(opr, 0, 8); // =,相等
neq: gen(opr, 0, 9); // #,不相等
lss: gen(opr, 0, 10); // <,小于
geq: gen(opr, 0, 11); // ],大于等于
gtr: gen(opr, 0, 12); // >,大于
leq: gen(opr, 0, 13); // [,小于等于
end
end
end
end {condition};
begin {statement}
if sym = ident then //如果是标识符
begin i := position(id); //查找符号表
if i = 0 then error(11) else //未找到,标识符未定义,报11号错
if table[i].kind <> varible then //如果标识符不是变量,报12号错
begin {assignment to non-varible} error(12); i := 0
end;
getsym; if sym = becomes then getsym else error(13); //如果是变量读入下一个TOKEN,不是赋值号,报13好错;是则读入一个TOKEN
expression(fsys); //调用表达是过程
if i <> 0 then //写指令
with table[i] do gen(sto, lev-level, adr)
end else
if sym = callsym then //如果是过程调用保留字,读入下一个TOKEN
begin getsym;
if sym <> ident then error(14) else //不是标识符报14号错
begin i := position(id);
if i = 0 then error(11) else //是标识符,未定义,报13号错
with table[i] do // 已定义的标识符读入类型
if kind=proc then gen(cal, lev-level, adr) //是过程名写指令
else error(15); //不是过程名,报15号错
getsym
end
end else
if sym = ifsym then //如果是IF
begin getsym; condition([thensym, dosym]+fsys); //读入一个TOKEN,调用条件判断过程
if sym = thensym then getsym else error(16); //如果是THEN,读入一个TOKEN,不是,报16号错
cx1 := cx; gen(jpc, 0, 0); //写指令
statement(fsys); code[cx1].a := cx
end else
if sym = beginsym then //如果是BEGIN
begin getsym; statement([semicolon, endsym]+fsys); //读入一个TOKEN
while sym in [semicolon]+statbegsys do
begin
if sym = semicolon then getsym else error(10); //如果读入的是分号
statement([semicolon, endsym]+fsys)
end;
if sym = endsym then getsym else error(17) //如果是END 读入一个TOKEN,不是,报17号错
end else
if sym = whilesym then //如果是WHILE
begin cx1 := cx; getsym; condition([dosym]+fsys); //调用条件过程
cx2 := cx; gen(jpc, 0, 0); //写指令
if sym = dosym then getsym else error(18); //如果是DO读入下一个TOKEN,不是报18号错
statement(fsys); gen(jmp, 0, cx1); code[cx2].a := cx
end;
test(fsys, [], 19)
end {statement};
begin {block}
dx:=3;
tx0:=tx;
table[tx].adr:=cx;
gen(jmp,0,0);
if lev > levmax then error(32);
repeat
if sym = constsym then //如果是CONST
begin getsym; //读入TOKEN
repeat constdeclaration; //常量声明
while sym = comma do
begin getsym; constdeclaration
end;
if sym = semicolon then getsym else error(5) //如果是分号读入下一个TOKEN,不是报5号错
until sym <> ident //不是标志符常量声明结束
end;
if sym = varsym then 如果是VAR
begin getsym; 读入下一个TOKEN
repeat vardeclaration; //变量声明
while sym = comma do
begin getsym; vardeclaration
end;
if sym = semicolon then getsym else error(5) //如果是分号读入下一个TOKEN,不是报5号错
until sym <> ident; //不是标志符常量声明结束
end;
while sym = procsym do //过程声明
begin getsym;
if sym = ident then
begin enter(proc); getsym
end
else error(4); //不是标志符报4号错
if sym = semicolon then getsym else error(5); //如果是分号读入下一个TOKEN,不是报5号错
block(lev+1, tx, [semicolon]+fsys);
if sym = semicolon then //如果是分号,取下一个TOKEN,不是报5号错
begin getsym;test(statbegsys+[ident,procsym],fsys,6)
end
else error(5)
end;
test(statbegsys+[ident], declbegsys, 7)
until not(sym in declbegsys); //取到的不是const var proc结束
code[table[tx0].adr].a := cx;
with table[tx0] do
begin adr := cx; {start adr of code}
end;
cx0 := 0{cx}; gen(int, 0, dx);
statement([semicolon, endsym]+fsys);
gen(opr, 0, 0); {return}
test(fsys, [], 8);
listcode;
end {block};
‘肆’ 编译原理四元式
四元式的一般形式为(op, arg1, arg2, result),其中:op为一个二元(也可以是零元或一元)运算符。arg1和arg2为两个运算对象,可以是变量、常数或者系统定义的临时变量名。result为运算结果。
第一步:T1=a*b,
第二步:T2=c*d,
第三步:T3=T2/e,
第四步:T4=T1-T3,
第五步:f=T4.
‘伍’ 什么是编译原理
问题一:什么是编译原理 编译:就是将程序语言进行翻译,生成可供用户直接执行的二进制代码,即可执行文件。
任务是个比较模糊的概念,指的是操作系统中正在进行的工作,既可以指进程,也可以指程序春坦灶。
程序指的是可以连续执行,并能够完成一定任务的一条条指令的 *** 。
进程是程序在一个数据 *** 上运行的过程,它是传统操作系统进行资源分配和调度的一个独立单位。
线程是一个指令执行序列,是操作系统调度的最小单位。一个或多个线程构成进程,构成一个进激的线程之间共享资源。进程和线程之间的最大区别就是线程不能独立拥有资源,进程拥有自己的资源。
问题二:编译原理中V*是什么意思 V是一个符号 *** ,假设V指的是三个符号a, b, c的 *** ,记为 V = {a, b, c }
V* 读作“V的闭包”,它的数学定义是V自身的任意多次自身连接(乘法)运算的积,也是一个 *** 。
也就是说,用V中的任意符号进行意多次(包括0次)连接,得到的符号串,都是V*这个 *** 中的元素。
0次连接的结果是不含任何符号的空串,记为 ε
1次连接就是只有一个符号的符号串,比如,a,b, c
2次连接是两个符号构成的符号串,比如,aa, ab, ac, ba, bb, bc,等等
……
n次连接是一个长度为n、由a、b、c三个符号构成的符号串,比如abaacbbac……
因此,V*包含一切由a,b,c三个符号连接而成的、任意长度的符号串(以及空串ε)
问题三:编译原理 V+什么意思,例如下面的例子。。。 v表示终结符和非终结符 *** 。
+表示 *** 中的一个或多个元素构成的串的 *** 。
所以v+表示由一个或多个终结符或非终结符构成的串的 *** 。比如如果a∈VT,A∈VN,那么a,A,aA,Aa,aAA,AaA等都是v+中的元素。
问题四:谁能够解释下编译原理中什么是FIRSTVT,和LASTVT,尽量浅显易懂点谢谢 Firstvt和Lastvt是为了画算符优先关系表的(就是表里面填优先大于小于等于的那个)。
然后要注意他们可都是终结符的 *** 。
Firstvt
找Firstvt的三条规则:如果要找A的Firstvt,A的候选式中出现:
A->a.......,即以终结符开头,该终结符入Firstvt
A->B.......,即以非终结符开头,该非终结符的Firstvt入A的Firstvt
攻 A->Ba.....,即先以非终结符开头,紧跟终结符,则终结符入Firstvt
Lastvt
找Lastvt的三条规则:如果要找A的Lastvt,A的候选式中出现:
A->.......a,即以终结符结尾,该终结符入Lastvt
A->.......B,即以非终结符结尾,该非终结符的Lastvt入A的Lastvt
A->.....aB,即先以非终结符结尾,前面是终结符,则终结符入Firstvt
问题五:编译原理 什么是语义分析 在编译原理中,语法规则和词法规则不同之处在于:规则主要识别单词,而语法主要识别多个单词组成的句子。词法分析信孝和词法分析程序:词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。词法分析程序实现这个任务。词法分析程序可以使用lex等工具自动生成。语法分析(Syntax *** ysis或Parsing)和语法分析程序(Parser) 语法分析是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分扒扮析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述.语义分析(Syntax *** ysis) 语义分析是编译过程的一个逻辑阶段. 语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查, 进行类型审查.语义分析将审查类型并报告错误:不能在表达式中使用一个数组变量,赋值语句的右端和左端的类型不匹配.
问题六:编译原理中,(E)是什么意思? E→(E)? 10分 就是 字符本身 意思是F产生( E ) 或者 i 比如If语句的开头 就是 带括号的 必须是 if(表达式)这样的形式 丢了任何即括号就是其 终结符 “(” 和 “)”.
问题七:大家觉得对编译器及编译原理需要掌握到一个什么程度 我跟你说,编译原理太有用了。
我是做手机游戏的,现在做一个游戏引擎。既然是引擎,就需要提供抽象的东西给上层使用。这里,我引入了脚本系统。
这个脚本系统包括一堆我根据实际需求自行设计的指令集,包括基本的输入输出,四则运算,系统功能调用,函数声明,调用等等(其实你要是用过lua或者其他游戏脚本你就知道了。)整个结构包括指令集、编译器、虚拟机等部分。这样,引擎提供一些基础服务,比如绘图,计算位置等,脚本就可以非常简单控制游戏。甚至快速构建新游戏。你应该知道QUAKE引擎吧?
这里提供给你一个计算器的小程序,应用了EBNF理论,支持表达式,比如(2+3*6)*4+4,你自己体验一下它的简洁和强大。
/*
simple integer arithmetic calculator according to the EBNF
-> {}
->+|-
->{}
-> *
-> ( )| Number
Input a line of text from stdin
Outputs Error or the result.
*/
#include
#include
#include
char token;/*global token variable*/
/*function prototypes for recursive calls*/
int exp(void);
int term(void);
int factor(void);
void error(void)
{
fprintf(stderr,Error\n);
exit(1);
}
void match(char expectedToken)
{
if(token==expectedToken)token=getchar();
else error();
}
main()
{
int result;
token = getchar();/*load token with first character for lookahead*/
result = exp();
if(token=='\n')/*check for end of line */
printf(Result = %d\n,result);
else error();/*extraneous cahrs on line*/
return 0;
}
int exp(void)
{
int temp = term();
while((token=='+')||(token=='-'))
switch(token)
{
case '+':
match('+');
temp+=term......>>
问题八:编译原理中,自动机究竟是什么. 形式语言
形式语言 是一个字母表上的某些有限长字串的 *** 。一个形式语言可以包含无限多个字串。
语言的形式定义
字母表 ∑ 为任意有限 *** ,ε 表示空串, 记 ∑ 0 为{ε},全体长度为 n 的字串为 ∑ n , ∑ * 为 ∑ 0 ∪∑ 1 ∪…∪∑ n ∪…, 语言 L 定义为 ∑ * 的任意子集。
注记:∑ * 的空子集 Φ 与 {ε} 是两个不同的语言。
语言间的运算
语言间的运算就是 ∑ * 幂集上的运算。
字串 *** 的交并补等运算。
连接运算:L 1 L 2 = { xy | x 属于L 1 并且 y 属于L 2 }。
幂运算:L n = L … L (共 n 个 L 连接在一起),L 0 = {ε}。
闭包运算:L * = L 0 ∪L 1 ∪…∪L n ∪…。
(右)商运算:L 1 /L 2 = {x | 存在 y 属于L 2 使得 xy 属于L 1 }。
语言的表示方法
一个形式语言可以通过多种方法来限定自身,比如:
枚举出各个字串(只适用于有限字串 *** )。
通过 形式文法 来产生(参见 乔姆斯基谱系 )。
通过正则表达式来产生。
通过某种自动机来识别,比如 图灵机 、 有限状态自动机 。
自动机
automata
对信号序列进行逻辑处理的装置。在自动控制领域内,是指离散数字系统的动态数学模型,可定义为一种逻辑结构,一种算法或一种符号串变换。自动机这一术语也广泛出现在许多其他相关的学科中,分别有不同的内容和研究目标。在计算机科学中自动机用作计算机和计算过程的动态数学模型,用来研究计算机的体系结构、逻辑操作、程序设计乃至计算复杂性理论。在语言学中则把自动机作为语言识别器,用来研究各种形式语言。在神经生理学中把自动机定义为神经网络的动态模型,用来研究神经生理活动和思维规律,探索人脑的机制。在生物学中有人把自动机作为生命体的生长发育模型,研究新陈代谢和遗传变异。在数学中则用自动机定义可计算函数,研究各种算法。现代自动机的一个重要特点是能与外界交换信息,并根据交换得来的信息改变自己的动作,即改变自己的功能,甚至改变自己的结构,以适应外界的变化。也就是说在一定程度上具有类似于生命有机体那样的适应环境变化的能力。
自动机与一般机器的重要区别在于自动机具有固定的内在状态,即具有记忆能力和识别判断能力或决策能力,这正是现代信息处理系统的共同特点。因此,自动机适宜于作为信息处理系统乃至一切信息系统的数学模型。自动机可按其变量集和函数的特性分类,也可按其抽象结构和联结方式分类。主要有:有限自动机和无限自动机、线性自动机和非线性自动机、确定型自动机和不确定型自动机、同步自动机和异步自动机、级联自动机和细胞自动机等。
这可能有你想要的答案
./question/7218281?fr=qrl3
问题九:编译原理中"(E)"表示什么 字符( 表达式 字符)
‘陆’ 编译原理 四元式
四元式是一种比较普遍采用的中间代码形式。
代码段的四元式表达式:
101 T:=0 (表达式为假的出口)
103 T:=1 (表达式为真的出口)
因为用户的表达式只有一个A<B,因此A<B的真假出口就是表达式的真假出口,所以
100: if a<b goto 103 (a<b为真,跳到真出口103)
101: T:=0(否则,进入假出口)
102: goto 104 (要跳过真出口,否则T的值不就又进入真出口了,为真)
103: T:=1
104:(程序继续执行)
(6)编译原理关系运算符扩展阅读:
四元式是一种更接近目标代码的中间代码形式。由于这种形式的中间代码便于优化处理,因此,在目前许多编译程序中得到了广泛的应用。
四元式实际上是一种“三地址语句”的等价表示。它的一般形式为:
(op,arg1,arg2,result)
其中, op为一个二元 (也可是一元或零元)运算符;arg1,arg2分别为它的两个运算 (或操作)对象,它们可以是变量、常数或系统定义的临时变量名;运算的结果将放入result中。四元式还可写为类似于PASCAL语言赋值语句的形式:
result ∶= arg1 op arg2
需要指出的是,每个四元式只能有一个运算符,所以,一个复杂的表达式须由多个四元式构成的序列来表示。例如,表达式A+B*C可写为序列
T1∶=B*C
T2∶=A+T1
其中,T1,T2是编译系统所产生的临时变量名。当op为一元、零元运算符 (如无条件转移)时,arg2甚至arg1应缺省,即result∶=op arg1或 op result ;对应的一般形式为:
(op,arg1,,result)
或
(op,,,result)
‘柒’ 编译原理5:算符优先关系表构造
根据FIRSTVT和LASTVT构造算符优先关系表,规则简单来讲如下:
① 对于产生式形如 A→...ab... 则优先级a=b
②对于产生式形如 A→...aBc...则优先级a=c,a<FIRSTVT(B),LASTVT(B)>c
例:
‘捌’ 编译原理:优先函数 f和g 到底怎么看啊,不懂怎么构造的 求解...
求算符优先函数的方法—迭代法
若已知运算符之间的优先关系,可按如下步骤构造优先函数:
1、对每个运算符a(包括#在内)令f(a)=g(a)=1
2、如果a⋗b且f(a)<=g(b),令f(a)=g(b)+1
3、如果a⋖b且f(a)>=g(b),令g(b)= f(a)+1
4、如果a≐b而f(a) ≠g(b),令min{f(a),g(b)}=max{f(a),g(b)}
5、重复2~4,直到过程收敛。如果重复过程中有一个值大于2n,则表明不存在算符优先函数。
‘玖’ 编译原理算符优先分析法中构造分析表的时候,井号和其他符号的优先级怎么判断在线等。
首先,算符优先分析法只考虑终结符之间的优先关系。
其次,#和其他终结符之间的优先关系按如下方法来确定:
1)假设文法的开始符为E,则增加一个产生式E‘-> #E#, E'不在原文法中出现
2)#<FIRSTVT(E) ; LASTVT(E)>#
‘拾’ 编译原理问题:求解
E是文法开头。ε代表终结符号(推理中代表终点或结果,程序语言中代表常量等)。E T 这些大写字母一般代表非终结符号(这些代表中间过程,非结果。程序中代表函数等等)。开始是E。因为有个G(E)。E就是文法开始符号。推导就有E开始,它也是一个非终结符(代表函数、或者一个推导过程,类似于程序中的main(c++)、winmain(vc++)、dllmain(dll)等主函数)。
1算术表达式文法:这个文法是一个递归文法。计算机进行逻辑推导时会走很多弯路(类似于遍历一颗树的过程)。为了不让计算机走弯路(提高效率的目的),可以变换为第二种文法。这种文法消除了递归(消除了歧义,类似于后缀表达式),使计算机可以一条直线走到底儿推导出结果。
我也很久没看编译原理了。 呵呵