解析四则表达式的编译过程及生成汇编代码

1、前序
这是编译原理的实验,自认为是上大学以来做过的最难的一个实验。
实验用到的基础知识:C语言、数据结构、汇编(只需简单的了解)。
开发工具:VC

2、问题描述
编译整数四则运算表达式,将整数四则运算表达式翻译为汇编语言代码。
消除左递归后的文法:
E→TE'
E'→+TE' |ε
T→FT'
T'→*FT' |ε
F→(E) | i
消除左递归后的翻译模式:
E ::= T {E'.i:=T.nptr}
E' {E.nptr:=E'.s}
E'::= + T {E'1.i:=mknode(‘+',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= - T {E'1.i:=mknode(‘-',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= ε {E'.s:= E'.i}
T ::= F {T'.i:=F.nptr}
T' {T.nptr:=T'.s}
T'::= * F {T'1.i:=mknode(‘*',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T'::= / F {T'1.i:=mknode(‘/',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T' ::= ε {T'.s:= T'.i}
F ::= (E) {F.nptr:=E.nptr}
F ::= num {F.nptr:=mkleaf(num,num.val)}

3、全局定义
test.c文件

复制代码 代码如下:

#ifndef TEST_C
#define TEST_C
/**
* 全局变量和全局函数文件
**/
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
/************************* 以下是全局变量(函数)的定义 *******************/
//输入的表达式最大长度,可以看做是缓冲区的长度
#define MAX_EXPRESSION_LENGTH 50
//存放输入的表达式
char expression[MAX_EXPRESSION_LENGTH];
//表达式字符数组的下标
int expression_index=0;
//存放一个单词符号
char strToken[MAX_EXPRESSION_LENGTH/2];
//判断是否是数字
int isNum(char * strToken)
{
int i=0;
while(strToken[i]){
if(!isdigit(strToken[i]))
break;
i++;
}
return strToken[i]==0;
}
//错误处理程序
void error(char* errerMessage)
{
printf("nERROR:%sn",errerMessage);
exit(0);
}
/************************* 以上是全局变量(函数)的定义 ******************/
#endif

4、词法分析
词法分析的要求是:接受一个表达式,输出该表达式中的各类单词符号
一般有两种方法来进行词法分析,一种是用状态图来实现,一种是用状态转换表。下面采用状态图实现
首先定义单词符号的种类和所属类型
typedef enum Symbol { ERR = -1, END, NUM, PLUS, MINUS, TIMES, SLASH, LPAREN, RPAREN } Symbol;

然后转态转换图如下所示:

test1.c文件用代码表示如下:

复制代码 代码如下:

#ifndef TEST1_C
#define TEST1_C
/**
* 采用状态图进行词法分析以及测试词法分析
*
**/
#include"test.c"
//枚举类型
typedef enum Symbol { ERR = -1, END, NUM, PLUS, MINUS, TIMES,
SLASH, LPAREN, RPAREN } Symbol;
//获取一个单词符号,该单词符号存放在strToken中。返回该单词符号的枚举类型
Symbol getToken();
//根据传入的枚举类型输出对应的单词符号
void printToken(Symbol i);
//测试词法分析
void testLexAnalyse();
//获取一个单词符号,该单词符号存放在strToken中。返回该单词符号的枚举类型
Symbol getToken()
{
char ch;
int state=0;//每次都是从状态0开始
int j=0;
//表达式遍历完成,单词符号为'#'
if(expression[expression_index]==''){
strToken[0]='#';
strToken[1]='';
return END;
}
while(1){
switch(state){
case 0:
//读取一个字符
ch=strToken[j++]=expression[expression_index++];
if(isspace(ch)){
j--;//注意退格
state=0;
}
else if(isdigit(ch))
state=1;
else if(ch=='+')
state=2;
else if(ch=='-')
state=3;
else if(ch=='*')
state=4;
else if(ch=='/')
state=5;
else if(ch=='(')
state=6;
else if(ch==')')
state=7;
else
return ERR;
break;
case 1:
ch=strToken[j++]=expression[expression_index++];
if(isdigit(ch))
state=1;
else{
expression_index--;
strToken[--j]=0;
return NUM;
}
break;
case 2:
strToken[j]=0;
return PLUS;
case 3:
strToken[j]=0;
return MINUS;
case 4:
strToken[j]=0;
return TIMES;
case 5:
strToken[j]=0;
return SLASH;
case 6:
strToken[j]=0;
return LPAREN;
case 7:
strToken[j]=0;
return RPAREN;
}
}
}
//根据传入的枚举类型输出对应的单词符号
void printToken(Symbol i){
switch(i){
case -1:printf("ERRn");break;
case 0:printf("ENDn");break;
case 1:printf("NUM %sn",strToken);break;
case 2:printf("PLUS %sn",strToken);break;
case 3:printf("MINUS %sn",strToken);break;
case 4:printf("TIMES %sn",strToken);break;
case 5:printf("SLASH %sn",strToken);break;
case 6:printf("LPAREN %sn",strToken);break;
case 7:printf("RPAREN %sn",strToken);break;
}
}
//测试词法分析
void testLexAnalyse()
{
Symbol tokenStyle;//单词符号类型
expression_index=0;
puts("n词法分析结果如下:");
while(1){
tokenStyle=getToken();
printToken(tokenStyle);
if(tokenStyle == ERR){
error("词法分析错误!");
}
if(tokenStyle == END){
break;
}
}
}

//主函数
int main()
{
gets(expression);
testLexAnalyse();
return 0;
}

#endif

运行结果

5、语法分析
要求:接受一个表达式,分析该表达式,并根据输入正确与否给出相应信息
主要是根据无左递归文法写出对应的各个子程序
test2.c

复制代码 代码如下:

#ifndef TEST_2
#define TEST_2
/**
* 语法分析以及测试语法分析
**/
#include"test1.c"
/*
消除左递归后的文法:
E→TE'
E'→+TE' |ε
T→FT'
T'→*FT' |ε
F→(E) | i
*/
//每个非终结符有对应的子程序函数声明
void E();
void E1();
void T();
void T1();
void F();
//测试语法分析
void testSyntaxAnalyse();
//每个非终结符有对应的子程序
void E()
{
T();
E1();
}
void E1()
{
if(strcmp(strToken,"+")==0 || strcmp(strToken,"-")==0){
getToken();
T();
E1();
}
//Follow(E1)={#,)}
else if(strcmp(strToken,"#")!=0 && strcmp(strToken,")")!=0){
error("语法分析错误!");
}
}
void T()
{
F();
T1();
}
void T1()
{
if(strcmp(strToken,"*")==0 || strcmp(strToken,"/")==0){
getToken();
F();
T1();
}
//Follow(T1)={+,#,)},如果考虑-号的话要加上-号
else if(strcmp(strToken,"-")!=0 &&strcmp(strToken,"+")!=0 && strcmp(strToken,"#")!=0 && strcmp(strToken,")")!=0){
error("语法分析错误!");
}
}
void F()
{
if(isNum(strToken)){
getToken();
}
else{
if(strcmp(strToken,"(")==0){
getToken();
E();
if(strcmp(strToken,")")==0)
getToken();
else
error("语法分析错误!");
}
else
error("语法分析错误!");
}
}
//测试语法分析
void testSyntaxAnalyse()
{
expression_index=0;
getToken();
E();
puts("n语法分析结果如下:");
if(strcmp(strToken,"#")!=0)
error("语法分析错误!");
else{
puts("语法分析正确!");
}
}
//主函数
int main()
{
gets(expression);
testLexAnalyse();
testSyntaxAnalyse();
return 0;
}
#endif

运行时要删掉test1.c中的主函数,运行结果

6、语义分析
要 求:需要实现的语义分析程序的功能是,接受一个表达式,分析该表达式,并在分析的过程中建立该表达式的抽象语法树。由于四则运算表达式的抽象语法树可基本 上看作是二叉树,因此中序遍历序列应该和输入的表达式一样——除了没有括号之外。可输出中序遍历序列检测程序功能是否正确。如果每个分支节点用一个临时变 量标记,则对四则运算表达式的抽象语法树进行后序遍历,可以得到输入表达式所对应的四元式序列
test3.c文件

复制代码 代码如下:

#ifndef TEST3_C
#define TEST3_C
/**
* 语义分析以及测试语义分析
* 其实这个实验是在test2的代码上进行修改
**/
#include"test1.c"
/*
消除左递归的翻译模式:
E ::= T {E'.i:=T.nptr}
E' {E.nptr:=E'.s}
E'::= + T {E'1.i:=mknode('+',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= - T {E'1.i:=mknode('-',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= ε {E'.s:= E'.i}
T ::= F {T'.i:=F.nptr}
T' {T.nptr:=T'.s}
T'::= * F {T'1.i:=mknode('*',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T'::= / F {T'1.i:=mknode('/',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T' ::= ε {T'.s:= T'.i}
F ::= (E) {F.nptr:=E.nptr}
F ::= num {F.nptr:=mkleaf(num,num.val)}
*/
#define MAX_LENGTH 20 //四元式中操作数的最大长度
typedef int ValType;
//结点类型
typedef struct ASTNode {
Symbol sym;//类型
ValType val;//值
struct ASTNode * left, *right;//左、右孩子
}ASTNode, *AST;
//四元式类型定义如下
typedef struct Quaternion{
char op;
char arg1[MAX_LENGTH];
char arg2[MAX_LENGTH];
char result[MAX_LENGTH];
}Quaternion;
//四元式数组,存放产生的四元式
Quaternion quaternion[MAX_LENGTH*2];
//统计四元式的个数
int count=0;
//后序遍历抽象语法树时存放操作数和临时变量,这里当作一个栈来使用
char stack[MAX_LENGTH*2][MAX_LENGTH];
//stack栈的下标
int index=0;
//内存中临时数据存储地址的偏移量
int t=-4;
//函数声明
ASTNode* E();
ASTNode* E1(ASTNode* E1_i);
ASTNode* T();
ASTNode* T1(ASTNode* T1_i);
ASTNode* F();
void error(char* errerMessage);
ASTNode *mknode(Symbol op, ASTNode *left, ASTNode *right);
ASTNode *mkleaf(Symbol sym, ValType val);
void yuyi_analyse();
void print_node(ASTNode *root);
void middle_list(ASTNode *root);
void last_list(ASTNode *root);
//测试语义分析
void testYuyiAnalyse();
//创建运算符结点
ASTNode *mknode(Symbol op, ASTNode *left, ASTNode *right);
//创建操作数结点
ASTNode *mkleaf(Symbol sym, ValType val);
//输出结点
void printNode(ASTNode *root);
//中序遍历二叉树
void middle_list(ASTNode *root);
//后序遍历二叉树
void last_list(ASTNode *root);
/*
E ::= T {E'.i:=T.nptr}
E' {E.nptr:=E'.s}
*/
//为右边的每个非终结符定义一个属性,返回E的综合属性
ASTNode* E()
{
ASTNode * E_nptr;
ASTNode * E1_i;
E1_i=T();
E_nptr=E1(E1_i);
return E_nptr;
}
/*
E'::= + T {E'1.i:=mknode('+',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= - T {E'1.i:=mknode('-',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= ε {E'.s:= E'.i}
*/
//返回的是综合属性,传递的是继承属性
ASTNode * E1(ASTNode *E1_i)
{
ASTNode * E11_i;
ASTNode * E1_s;
ASTNode * T_nptr;
char oper;
if(strcmp(strToken,"+")==0 || strcmp(strToken,"-")==0){
oper=strToken[0];
getToken();
T_nptr=T();
if(oper=='+')
E11_i=mknode(PLUS,E1_i,T_nptr);
else
E11_i=mknode(MINUS,E1_i,T_nptr);
E1_s=E1(E11_i);
}
//Follow(E1)={#,)},可以匹配空串
else if(strcmp(strToken,"#")==0 || strcmp(strToken,")")==0){
E1_s=E1_i;
}else{
error("语法分析错误!");
}
return E1_s;
}
/*
T ::= F {T'.i:=F.nptr}
T' {T.nptr:=T'.s}
*/
ASTNode* T()
{
ASTNode * T_nptr;
ASTNode * T1_i;
T1_i=F();
T_nptr=T1(T1_i);
return T_nptr;
}
/*
T'::= * F {T'1.i:=mknode('*',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T'::= / F {T'1.i:=mknode('/',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T' ::= ε {T'.s:= T'.i}
*/
ASTNode* T1(ASTNode* T1_i)
{
ASTNode* F_nptr;
ASTNode* T11_i;
ASTNode* T1_s;
char oper;
if(strcmp(strToken,"*")==0 || strcmp(strToken,"/")==0){
oper=strToken[0];
getToken();
F_nptr=F();
if(oper=='*')
T11_i=mknode(TIMES,T1_i,F_nptr);
else
T11_i=mknode(SLASH,T1_i,F_nptr);
T1_s=T1(T11_i);
}
//Follow(T1)={+,#,)},如果考虑-号的话要加上-号
else if(strcmp(strToken,"-")==0 || strcmp(strToken,"+")==0 || strcmp(strToken,"#")==0 || strcmp(strToken,")")==0){
T1_s=T1_i;
}else{
error("语法分析错误!");
}
return T1_s;
}
/*
F ::= (E) {F.nptr:=E.nptr}
F ::= num {F.nptr:=mkleaf(num,num.val)}
*/
ASTNode* F()
{
ASTNode* F_nptr;
ASTNode* E_nptr;
if(isNum(strToken)){
F_nptr=mkleaf(NUM,atoi(strToken));
getToken();
}
else{
if(strcmp(strToken,"(")==0){
getToken();
E_nptr=E();
if(strcmp(strToken,")")==0)
getToken();
else
error("语法分析错误!");
F_nptr=E_nptr;
}
else {
error("语法分析错误!");
}
}
return F_nptr;
}
//创建运算符结点
ASTNode *mknode(Symbol op, ASTNode *left, ASTNode *right)
{
ASTNode* p=(ASTNode*)malloc(sizeof(ASTNode));
p->left=left;
p->right=right;
p->sym=op;
p->val=0;
return p;
}
//创建操作数结点
ASTNode *mkleaf(Symbol sym, ValType val)
{
ASTNode* p=(ASTNode*)malloc(sizeof(ASTNode));
p->sym=sym;
p->val=val;
p->left=NULL;
p->right=NULL;
return p;
}
//输出结点
void printNode(ASTNode *root)
{
if(root->sym==NUM)
printf("%d ",root->val);
else if(root->sym==PLUS)
printf("+ ");
else if(root->sym==MINUS)
printf("- ");
else if(root->sym==TIMES)
printf("* ");
else if(root->sym==SLASH)
printf("/ ");
}
//中序遍历二叉树
void middle_list(ASTNode *root)
{
if(root==NULL)
return ;
middle_list(root->left);
printNode(root);
middle_list(root->right);
}
//后序遍历二叉树
void last_list(ASTNode *root)
{
char temp[MAX_LENGTH];
if(root==NULL)
return ;
last_list(root->left);
last_list(root->right);
if(root->sym == NUM){//如果是数字,则直接存入栈中
sprintf(temp,"%d",root->val);
strcpy(stack[index++],temp);
}
else if(root->sym == PLUS){//如果是+号,产生一个四元式
//给四元式赋值
quaternion[count].op='+';
strcpy(quaternion[count].arg2,stack[--index]);
strcpy(quaternion[count].arg1,stack[--index]);
sprintf(quaternion[count].result,"t+%d",t+=4);
strcpy(stack[index++],quaternion[count].result);
//输出该四元式
printf("%-4c%-8s%-8s%-8sn",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);
count++;
}else if(root->sym == MINUS){//如果是+号,产生一个四元式
quaternion[count].op='-';
strcpy(quaternion[count].arg2,stack[--index]);
strcpy(quaternion[count].arg1,stack[--index]);
sprintf(quaternion[count].result,"t+%d",t+=4);
strcpy(stack[index++],quaternion[count].result);
printf("%-4c%-8s%-8s%-8sn",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);
count++;
}else if(root->sym == TIMES){//如果是*号,产生一个四元式
quaternion[count].op='*';
strcpy(quaternion[count].arg2,stack[--index]);
strcpy(quaternion[count].arg1,stack[--index]);
sprintf(quaternion[count].result,"t+%d",t+=4);
strcpy(stack[index++],quaternion[count].result);
printf("%-4c%-8s%-8s%-8sn",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);
count++;
}else if(root->sym == SLASH){
quaternion[count].op='/';
strcpy(quaternion[count].arg2,stack[--index]);
strcpy(quaternion[count].arg1,stack[--index]);
sprintf(quaternion[count].result,"t+%d",t+=4);
strcpy(stack[index++],quaternion[count].result);
printf("%-4c%-8s%-8s%-8sn",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);
count++;
}
}
//测试语义分析
void testYuyiAnalyse()
{
ASTNode *root;
expression_index=0;
getToken();
root=E();
puts("n语义分析结果如下:");
printf("中序遍历:");
middle_list(root);
putchar('n');
printf("后序遍历得到的四元式:n");
last_list(root);
putchar('n');
}
//主函数
int main()
{
gets(expression);
testYuyiAnalyse();
return 0;
}
#endif

运行结果

7、代码生成
要求:以实验3的语义分析程序的四元式输出作为输入,输出汇编语言程序。
test4.c

复制代码 代码如下:

#ifndef TEST4_C
#define TEST4_C
/**
* 生产汇编代码
**/
#include"test3.c"
//传人一个四元式,输出对应的汇编代码
void print_code(Quaternion qua)
{
putchar('n');
/*
mov eax, 3
add eax, 4
mov t+0, eax
*/
if(qua.op == '+'){
printf(" mov eax,%sn",qua.arg1);
printf(" add eax,%sn",qua.arg2);
printf(" mov %s,eaxn",qua.result);
}else if(qua.op == '-'){
printf(" mov eax,%sn",qua.arg1);
printf(" sub eax,%sn",qua.arg2);
printf(" mov %s,eaxn",qua.result);
}
/*
mov eax, 2
mov ebx, t+0
mul ebx
mov t+4, eax
*/
else if(qua.op == '*'){
printf(" mov eax,%sn",qua.arg1);
printf(" mov ebx,%sn",qua.arg2);
printf(" mul ebxn");
printf(" mov %s,eaxn",qua.result);
}else if(qua.op == '/'){//除法的时候不考虑余数
printf(" mov eax,%sn",qua.arg1);
printf(" mov ebx,%sn",qua.arg2);
printf(" div ebxn");
printf(" mov %s,eaxn",qua.result);
}
}
//输出全部汇编代码
void testCode()
{
int i=0;
puts("生成的汇编代码如下:n");
puts(".386");
puts(".MODEL FLAT");
puts("ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD");
puts("INCLUDE io.h ; header file for input/output");
puts("cr EQU 0dh ; carriage return character");
puts("Lf EQU 0ah ; line feed");
puts(".STACK 4096 ; reserve 4096-byte stack");
puts(".DATA ; reserve storage for data");
puts("t DWORD 40 DUP (?)");
puts("label1 BYTE cr, Lf, "The result is "");
puts("result BYTE 11 DUP (?)");
puts(" BYTE cr, Lf, 0");
puts(".CODE ; start of main program code");
puts("_start:");
//遍历实验3中的四元式,输出对应的汇编代码
for(;i<count;i++)
print_code(quaternion[i]);
puts(" dtoa result, eax ; convert to ASCII characters");
puts(" output label1 ; output label and sum");
puts(" INVOKE ExitProcess, 0 ; exit with return code 0");
puts("PUBLIC _start ; make entry point public");
puts("END ; end of source code");
}
//主函数
int main()
{
gets(expression);
testLexAnalyse();
testYuyiAnalyse();
testCode();
return 0;
}
#endif

运行结果

8、点击下载源代码

时间: 2024-08-29 03:40:36

解析四则表达式的编译过程及生成汇编代码的相关文章

解析四则表达式的编译过程及生成汇编代码_C 语言

1.前序这是编译原理的实验,自认为是上大学以来做过的最难的一个实验.实验用到的基础知识:C语言.数据结构.汇编(只需简单的了解).开发工具:VC 2.问题描述编译整数四则运算表达式,将整数四则运算表达式翻译为汇编语言代码.消除左递归后的文法:E→TE'E'→+TE' |εT→FT'T'→*FT' |εF→(E) | i消除左递归后的翻译模式:E ::=     T    {E'.i:=T.nptr}E'    {E.nptr:=E'.s}E'::=      + T  {E'1.i:=mknod

Visual Studio 2005 XviD编译过程

这几天做一个BMP2AVI的转换器,要用到XviD Codec的编码器,使用过程中,发现有一个Status窗口弹出来,压缩过程奇慢GraphEdit里的结构如下:PushSourceBitmapSetFilter -> XviD MPEG-4 Codec -> AVI Mux -> FileWriter并且关闭GraphEdit的时候,关闭不了程序,程序失去响应,怀疑是因为Status窗口造成的,google上搜索了一下,发现需要修改XviD的源代码来去掉这个东西.参见http://to

C语言的编译过程

C语言的编译链接过程要把编写的c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接. 编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程. 链接是把目标文件.操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程. 过程图解如下: 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程. 编译过程 编译过程又可以分成两个阶段:编译和会汇编. 编译        编译是读取源程序(字符流),对之进行

UNIX系统管理:编译过程概述

了解一些编译知识的读者都知道,所谓编译,就是在编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序. UNIX环境下的C编译系统所遵循的也是这么一个一般的过程.值得注意的是这个过程并不是有某个单个程序完成的,而是有多个分别完成某一方面工作的程序组合完成的.这一http://www.aliyun.com/zixun/aggregation/8511.html">设计

C++计算四则表达式的模板

一个很方便的C++函数模板,可以并 且只可以计算含括号的四则表达式,只有一个函数接口:int GetExpValue (_Tstream& istrin, _T& nReturn) 参数解释: istrin: 一个输入流,可以是标准IO流,可以是文件流,也可以是串流 nReturn:用于接收计算结果的变量,计算所使用的类型由这个变量确定 返回值: 返回非0表示计算成功,0表示计算失败有错误 程序代码: 以下是引用片段: namespace fy_Exp{ namespace {templa

WinCE系统的编译过程图解

在WinCE系统中,当我们完成了相关的开发和系统定制工作以后,会编译WinCE系统,最后生成NK.bin和NK.nb0.我现在用WinCE6.0在自己的PC上面编译一次用时19分16秒(有一天无聊,就测了一下).下面介绍一下WinCE系统的编译过程,大致分为4个阶段:编译阶段(Compile phase),系统产生阶段(Sysgen phase),文件拷贝阶段(Release copy phase)和生成映像阶段(Make Run-time image phase). 过程如图: 从图中可以看出

iOS编译过程的原理和应用

前言 一般可以将编程语言分为两种,编译语言和直译式语言. 像C++,Objective C都是编译语言.编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高. 像JavaScript,Python都是直译式语言.直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码.所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活,也就是为啥JS大法好. iOS开发目前的常用语言是:Objective和Swif

《深入理解Android:Telephony原理剖析与最佳实践》一2.2 Android源代码下载及编译过程

2.2 Android源代码下载及编译过程 前面完成了Ubuntu.JDK.Android SDK的安装和配置,接着开始下载和编译Android 4.0源代码,这个过程简单但花费的时间比较长,请读者先有个心理准备. Android 4.0的代号为Ice Cream Sandwich,简称ICS,中文名称冰淇淋三明治. 2.2.1 工作目录设置 本书采用ICS名称的文件夹作为Android 4.0源代码的根目录,在用户根目录下新建代码根目录ICS文件夹,并设置此目录为工作目录,在.bashrc中增

堆栈解析算术表达式

中缀表达式就是通常所说的算术表达式,比如(1+2)*3-4. 后缀表达式是指通过解析后,运算符在运算数之后的表达式,比如上式解析成后缀表达式就是12+3*4-.这种表达式可以直接利用栈来求解.中缀->后缀 就是运算符的出入栈,操作数直接输出,运算符按优先级高(低)是入(出)栈. 运算符的优先级 优先级 运算符 1 括号() 2 负号- 3 乘方** 4 乘*,除/,求余% 5 加+,减- 6 小于<,小于等于<=,大于>,大于等于>= 7 等于==,不等于!= 8 逻辑与&a