(完整word版)PL0源代码(C语言版)
/*PL/0 编译系统C版本头文件pl0.h*/
# define norw 13 //a number of reserved word /*关键字个数*/
# define txmax 100 //length of identifier table /*名字表容量*/
# define nmax 14 //max number of digits in numbers /*number的最大位数*/ # define al 10 //length of identifier /*符号的最大长度*/
# define amax 2047 //maximum address /*地址上界*/
# define levmax 3 //max depth of block nesting /*最大允许过程嵌套声明层数[0,lexmax]*/
# define cxmax 200 //size of code array /*最多的虚拟机代码数*/
/*符号*/
enum symbol{
nul, ident, number, plus, minus,
times, slash, oddsym, eql, neq, //slash斜线
lss, leq, gtr, geq, lparen, //leq :less than or equal to; gtr: great than;lparen:left parenthesis
rparen, comma, semicolon,period, becomes,//comma逗号semicolon分号period句号becomes赋值号
beginsym, endsym, ifsym, thensym, whilesym,
writesym, readsym, dosym, callsym, constsym,
varsym, procsym,
};
#define symnum 32
/*-------------*/
enum object{ //object为三种标识符的类型
constant,
variable,
procedur,
};
/*--------------*/
enum fct{ //fct类型分别标识类PCODE的各条指令
lit, opr, lod, sto, cal, inte, jmp, jpc, //书本P23
};
#define fctnum 8
/*--------------*/
struct instruction //指令
{
enum fct f; //功能码
int l; //层次差
int a; //P23
};
FILE * fas; //输出名字表
FILE * fa; //输出虚拟机代码
FILE * fa1; //输出源文件及其各行对应的首地址
FILE * fa2; //输出结果
bool tableswitch; //显示名字表与否
bool listswitch; //显示虚拟机代码与否
char ch; //获取字符的缓冲区,getch使用
enum symbol sym; //当前符号
char id[al+1]; //当前ident,多出一个字节用于存放0
int num; //当前number
int cc,ll; //getch使用的计数器,cc表示当前字符(ch)的位置
int cx; //虚拟机代码指针,取值范围[0,cxmax-1]
char line[81]; //读取行缓冲区
char a[al+1]; //临时符号,多出的一个字节用于存放0
struct instruction code[cxmax]; //存放虚拟机代码的数组
char word[norw][al]; //保留字
enum symbol wsym[norw]; //保留字对应的符号值
enum symbol ssym[256]; //单字符的符号值
char mnemonic[fctnum][5]; //虚拟机代码指令名称
bool declbegsys[symnum]; //表示声明开始的符号集合,declaring begin symbol set bool statbegsys[symnum]; //表示语句开始的符号集, statement
bool facbegsys[symnum]; //表示因子开始的符号集合,factor
/*------------------------------*/
struct tablestruct
{
char name[al]; /*名字*/
enum object kind; /*类型:const,var,array or procedure*/ int val; /*数值,仅const使用*/
int level; /*所处层,仅const不使用*/
int adr; /*地址,仅const不使用*/
int size; /*需要分配的数据区空间,仅procedure使用*/
};
struct tablestruct table[txmax]; /*名字表*/
FILE * fin; //fin文本文件用于指向输入的源程序文件
FILE* fout; //fout文本文件用于指向输出的文件
char fname[al];
int err; /*错误计数器*/
/*当函数中会发生fatal error时,返回-1告知调用它的函数,最终退出程序*/
#define getsymdo if(-1==getsym())return -1
#define getchdo if(-1==getch())return -1
#define testdo(a,b,c) if(-1==test(a,b,c))return -1
#define gendo(a,b,c) if(-1==gen(a,b,c))return -1
#define expressiondo(a,b,c) if(-1==expression(a,b,c))return -1
#define factordo(a,b,c) if(-1==factor(a,b,c))return -1
#define termdo(a,b,c) if(-1==term(a,b,c))return -1
#define conditiondo(a,b,c) if(-1==condition(a,b,c))return -1
#define statementdo(a,b,c) if(-1==statement(a,b,c))return -1
#define constdeclarationdo(a,b,c) if(-1==constdeclaration(a,b,c))return -1 #define vardeclarationdo(a,b,c) if(-1==vardeclaration(a,b,c))return -1 void error(int n);
int getsym();
int getch();
void init();
int gen(enum fct x,int y,int z);
int test(bool*s1,bool*s2,int n);
int inset(int e,bool*s);
int addset(bool*sr,bool*s1,bool*s2,int n);
int subset(bool*sr,bool*s1,bool*s2,int n);
int mulset(bool*sr,bool*s1,bool*s2,int n);
int block(int lev,int tx,bool* fsys);
void interpret();
int factor(bool* fsys,int* ptx,int lev);
int term(bool*fsys,int*ptx,int lev);
int condition(bool*fsys,int*ptx,int lev);
int expression(bool*fsys,int*ptx,int lev);
int statement(bool*fsys,int*ptx,int lev);
void listcode(int cx0);
int vardeclaration(int* ptx,int lev, int* pdx);
int constdeclaration(int* ptx,int lev, int* pdx);
int position(char* idt,int tx);
void enter(enum object k,int* ptx,int lev,int* pdx);
int base(int l,int* s,int b);
//A.2 C 版本
/*编译和运行环境:
*1Visual C++6.0,VisualC++.NET and Visual C++.NET 2003
*WinNT, Win 200, WinXP and Win2003
*2 gcc version 3.3.2 20031022(Red Hat Linux 3.3.2-1)
*Redhat Fedora core 1
*Intel 32 platform
*使用方法:
*运行后输入PL/0 源程序文件名
*回答是否输出虚拟机代码
*回答是否输出名字表
*fa.tmp 输出虚拟机代码
*fa1.tmp 输出源文件及其各行对应的首地址
*fa2.tmp 输出结果
*fas.tmp 输出名字表
*/
#include
#include"pl0.h"
#include"string.h"
/*解释执行时使用的栈*/
#define stacksize 500
int main()
{
bool nxtlev[symnum];
printf("Input pl/0 file ?");
scanf("%s",fname); /*输入文件名*/
fin=fopen(fname,"r"); //返回值:文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno 中
if(fin)
{
printf("List object code ?(Y/N)"); /*是否输出虚拟机代码*/
scanf("%s",fname);
listswitch=(fname[0]=='y'||fname[0]=='Y');
printf("List symbol table ? (Y/N)"); /*是否输出名字表*/
scanf("%s",fname);
tableswitch=(fname[0]=='y'||fname[0]=='Y');
fa1=fopen("fa1.tmp","w");
fprintf(fa1,"Iput pl/0 file ?");
fprintf(fa1,"%s\n", fname);
init(); /*初始化*/
err=0; //错误计数器置0
cc=cx=ll=0;
ch=' ';
if(-1!=getsym())
{
fa=fopen("fa.tmp","w");
fas=fopen("fas.tmp","w");
addset(nxtlev,declbegsys,statbegsys,symnum);
nxtlev[period]=true;
if(-1==block(0,0,nxtlev)) /*调用编译程序*/
{
fclose(fa);
fclose(fa1);
fclose(fas);
fclose(fin);
printf("\n");
return 0;
}
fclose(fa);
fclose(fa1);
fclose(fas);
if(sym!=period)
{
error(9);
}
if(err==0)
{
fa2=fopen("fa2.tmp", "w");
interpret();
fclose(fa2);
}
else
{
printf("Errors in pl/0 program");
}
}
fclose(fin);
}
else
{
printf("Can't open file! \n");
}
printf("\n");
return 0;
}
/*
*初始化
*/
void init()
{
int i;
for(i=0;i<=255;i++)
{
ssym[i]=nul; //ssym:单字符的符号值}
ssym['+']=plus;
ssym['-']=minus;
ssym['*']=times;
ssym['/']=slash;
ssym['(']=lparen;
ssym[')']=rparen;
ssym['=']=eql;
ssym[',']=comma;
ssym['.']=period;
ssym['#']=neq;
ssym[';']=semicolon;
/*设置保留字名字,按照字母顺序,便于折半查找*/ strcpy(&(word[0][0]),"begin");
strcpy(&(word[1][0]),"call");
strcpy(&(word[2][0]),"const");
strcpy(&(word[3][0]),"do");
strcpy(&(word[4][0]),"end");
strcpy(&(word[5][0]),"if");
strcpy(&(word[6][0]),"odd");
strcpy(&(word[7][0]),"procedure");
strcpy(&(word[8][0]),"read");
strcpy(&(word[9][0]),"then");
strcpy(&(word[10][0]),"var");
strcpy(&(word[11][0]),"while");
strcpy(&(word[12][0]),"write");
/*设置保留字符号*/
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=constsym;
wsym[3]=dosym;
wsym[4]=endsym;
wsym[5]=ifsym;
wsym[6]=oddsym;
wsym[7]=procsym;
wsym[8]=readsym;
wsym[9]=thensym;
wsym[10]=varsym;
wsym[11]=whilesym;
wsym[12]=writesym;
/*设置指令名称*/
strcpy(&(mnemonic[lit][0]),"lit");
strcpy(&(mnemonic[opr][0]),"opr");
strcpy(&(mnemonic[lod][0]),"lod");
strcpy(&(mnemonic[sto][0]),"sto");
strcpy(&(mnemonic[cal][0]),"cal");
strcpy(&(mnemonic[inte][0]),"int");
strcpy(&(mnemonic[jmp][0]),"jmp");
strcpy(&(mnemonic[jpc][0]),"jpc");
/*设置符号集*/
for(i=0;i { declbegsys[i]=false; statbegsys[i]=false; facbegsys[i]=false; } /*设置声明开始符号集*/ declbegsys[constsym]=true; declbegsys[varsym]=true; declbegsys[procsym]=true; /*设置语句开始符号集*/ statbegsys[beginsym]=true; statbegsys[callsym]=true; statbegsys[ifsym]=true; statbegsys[whilesym]=true; /*设置因子开始符号集*/ facbegsys[ident]=true; facbegsys[number]=true; facbegsys[lparen]=true; } /* *用数组实现集合的集合运算 */ int inset(int e,bool* s) { return s[e]; } int addset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;i { sr[i]=s1[i]||s2[i]; } return 0; } int subset(bool* sr,bool* s1,bool* s2,int n) { int i; for(i=0;i { sr[i]=s1[i]&&(!s2[i]); } return 0; } int mulset(bool* sr,bool* s1,bool* s2,int n) { int i; for(i=0;i { sr[i]=s1[i]&&s2[i]; } return 0; } /* *出错处理,打印出错位置和错误编码 */ void error(int n) { char space[81]; memset(space,32,81); printf("-------%c\n",ch); space[cc-1]=0;//出错时当前符号已经读完,所以cc-1 printf("****%s!%d\n",space,n); err++; } /* * 漏掉空格,读取一个字符 * * 每次读一行,存入line缓冲区,line被getsym取空后再读一行* * 被函数getsym调用 int getch() { if(cc==ll) { if(feof(fin)) //如果文件结束,则返回非0值,否则返回0,文件结束符只能被clearerr()清除。 { printf("program incomplete"); return -1; } ll=0; cc=0; printf("%d ",cx ); fprintf(fa1,"%d ",cx); ch=' '; while(ch!=10) { //fscanf(fin,"%c",&ch) if(EOF==fscanf(fin,"%c",&ch)) { line[ll]=0; break; } printf("%c",ch); fprintf(fa1,"%c",ch); line[ll]=ch; ll++; } printf("\n"); fprintf(fa1,"\n"); } ch=line[cc]; cc++; return 0; } /*词法分析,获取一个符号流程图P19 */ int getsym() { int i,j,k; while( ch==' '||ch==10||ch==9) //忽略空格、换行、TAB { getchdo; //getchdo :if(-1==getch())return -1 } if(ch>='a'&&ch<='z') { k=0; do{ if(k { a[k]=ch; k++; } getchdo; }while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9'); a[k]=0; strcpy(id,a); i=0; j=norw-1; do{ k=(i+j)/2; if(strcmp(id,word[k])<=0) { j=k-1; } if(strcmp(id,word[k])>=0) { i=k+1; } }while(i<=j); if(i-1>j) { sym=wsym[k]; } else { sym=ident; } } else { if(ch>='0'&&ch<='9') { k=0; num=0; sym=number; do{ num=10*num+ch-'0'; k++; getchdo; }while(ch>='0'&&ch<='9'); /*获取数字的值*/ k--; if(k>nmax) { error(30); } } else { if(ch==':') /*检测赋值符号*/ { getchdo; if(ch=='=') { sym=becomes; getchdo; } else { sym=nul; /*不能识别的符号*/ } } else { if(ch=='<') /*检测小于或小于等于符号*/ { getchdo; if(ch=='=') { sym=leq; getchdo; } else { sym=lss; } } else { if(ch=='>') /*检测大于或大于等于符号*/ { getchdo; if(ch=='=') { sym=geq; getchdo; } else { sym=gtr; } } else { sym=ssym[ch];/* 当符号不满足上述条件时,全部按照单字符号处理*/ //getchdo; //richard if(sym!=period) { getchdo; } //end richard } } } } } return 0; } /* *生成虚拟机代码 * *x:instruction.f; *y:instruction.l; *z:instruction.a; */ int gen(enum fct x,int y,int z) { if(cx>=cxmax) { printf("Program too long"); /*程序过长*/ return -1; } code[cx].f=x; code[cx].l=y; code[cx].a=z; cx++; return 0; } /* *测试当前符号是否合法 * *在某一部分(如一条语句,一个表达式)将要结束时时我们希望下一个符号属于某集合*(该部分的后跟符号)test 负责这项检测,并且负责当检测不通过时的补救措施 *程序在需要检测时指定当前需要的符号集合和补救用的集合(如之前未完成部分的后跟*符号),以及不通过时的错误号 * *S1:我们需要的符号 *s2:如果不是我们需要的,则需要一个补救用的集合 *n:错误号 */ int test(bool* s1,bool* s2,int n) { if(! inset(sym,s1)) { error(n); /*当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合*/ while((! inset(sym,s1))&&(! inset(sym,s2))) { getsymdo; } } return 0; } /* *编译程序主体 * *lev:当前分程序所在层 *tx:名字表当前尾指针 *fsys:当前模块后跟符号集合 */ int block(int lev,int tx,bool* fsys) { int i; int dx; /*名字分配到的相对地址*/ int tx0; /*保留初始tx*/ int cx0; /*保留初始cx*/ bool nxtlev[symnum]; /*在下级函数的参数中,符号集合均为值参,但由于使用数组 实现,传递进来的是指针,为防止下级函数改变上级函数的 集合,开辟新的空间传递给下级函数*/ dx=3; tx0=tx; /*记录本层名字的初始位置*/ table[tx].adr=cx; gendo(jmp,0,0); if(lev > levmax) { error(32); } do{ if(sym==constsym) /*收到常量声明符号,开始处理常量声明*/ { getsymdo; do{ constdeclarationdo(&tx,lev,&dx); /*dx的值会被constdeclaration改变,使用 指针*/ while(sym==comma) { getsymdo; constdeclarationdo(&tx,lev,&dx); } if(sym==semicolon) { getsymdo; } else { error(5); /*漏掉了逗号或者分号*/ } }while(sym==ident); } if(sym==varsym)/*收到变量声名符号,开始处理变量声名*/ { getsymdo; do{ vardeclarationdo(&tx,lev,&dx); while(sym==comma) { getsymdo; vardeclarationdo(&tx,lev,&dx); } if(sym==semicolon) { getsymdo; } else { error(5); } }while(sym==ident); } while(sym==procsym)/*收到过程声名符号,开始处理过程声名*/ { getsymdo; if(sym==ident) { enter(procedur,&tx,lev,&dx);/*记录过程名字*/ getsymdo; } else { error(4);/*procedure后应为标识符*/ } if(sym==semicolon) { getsymdo; } else { error(5);/*漏掉了分号*/ } memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[semicolon]=true; if(-1==block(lev+1,tx,nxtlev)) { return -1;/*递归调用*/ } if(sym==semicolon) { getsymdo; memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlev[ident]=true; nxtlev[procsym]=true; testdo(nxtlev,fsys,6); } else { error(5); /*漏掉了分号*/ } } memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlev[ident]=true; nxtlev[period]=true; testdo(nxtlev,declbegsys,7); }while(inset(sym,declbegsys)); /*直到没有声明符号*/ code[table[tx0].adr].a=cx; /*开始生成当前过程代码*/ table[tx0].adr=cx; /*当前过程代码地址*/ table[tx0].size=dx; /*声明部分中每增加一条声明都会给dx增加1,声明部分已经结束,dx就是当前过程数据的size*/ cx0=cx; gendo(inte,0,dx); /*生成分配内存代码*/ if(tableswitch) /*输出名字表*/ { printf("TABLE:\n"); if(tx0+1>tx) { printf("NULL\n"); } for(i=tx0+1;i<=tx;i++) { switch(table[i].kind) { case constant: printf("%d const %s",i,table[i].name); printf("val=%d\n",table[i].val); fprintf(fas,"%d const %s",i,table[i].name); fprintf(fas,"val=%d\n",table[i].val); break; case variable: printf("%d var%s",i,table[i].name); printf("lev=%d addr=%d\n",table[i].level,table[i].adr); fprintf(fas,"%d var %s",i,table[i].name); fprintf(fas,"lev=%d addr=%d\n",table[i].level,table[i].adr); break; case procedur: printf("%d proc%s",i,table[i].name); printf("lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size); fprintf(fas,"%d proc%s",i,table[i].name); fprintf(fas,"lev=%d adr=%d size=%d \n",table[i].level,table[i].adr,table[i].size); break; } } printf("\n"); } /*语句后跟符号为分号或end*/ memcpy(nxtlev,fsys,sizeof(bool)*symnum);/*每个后跟符号集和都包含上层后跟符号集和,以便补救*/ nxtlev[semicolon]=true; nxtlev[endsym]=true; statementdo(nxtlev,&tx,lev); gendo(opr,0,0); /*每个过程出口都要使用的释放数据段命令*/ memset(nxtlev,0,sizeof(bool)*symnum); /*分程序没有补救集合*/ test(fsys,nxtlev,8); /*检测后跟符号正确性*/ listcode(cx0); /*输出代码*/ return 0; } /* *在名字表中加入一项 * *k:名字种类const,var or procedure *ptx:名字表尾指针的指针,为了可以改变名字表尾指针的数值 *lev:名字所在的层次,以后所有的lev都是这样 *pdx:为当前应分配的变量的相对地址,分配后要增加1 */ void enter (enum object k,int *ptx,int lev, int *pdx) { (*ptx)++; strcpy(table[(*ptx)].name,id); /*全局变量id中已存有当前名字的名字*/ table[(*ptx)].kind=k; switch(k) { case constant: /*常量名字*/ if (num>amax) { error(31); num=0; } table[(*ptx)].val=num; break; case variable: /*变量名字*/ table[(*ptx)].level=lev; table[(*ptx)].adr=(*pdx); (*pdx)++; break; /*过程名字*/ case procedur: table[(*ptx)].level=lev; break; } } /* *查找名字的位置 *找到则返回在名字表中的位置,否则返回0 * *idt: 要查找的名字 *tx::当前名字表尾指针 */ int position(char * idt,int tx) { int i; strcpy(table[0].name,idt); i=tx; while(strcmp(table[i].name,idt)!=0) { i--; } return i; } /* *常量声明处理 */ int constdeclaration(int * ptx,int lev,int * pdx) { if(sym==ident) { getsymdo; if(sym==eql ||sym==becomes) { if(sym==becomes) { error(1); /*把=写出成了:=*/ } getsymdo; if(sym==number) { enter(constant,ptx,lev,pdx); getsymdo; } else { error(2); /*常量说明=后应是数字*/ } } else { error(3); /*常量说明标识后应是=*/ } } else { error(4); /*const后应是标识*/ } return 0; } /* * */ int vardeclaration(int * ptx,int lev,int * pdx) { if(sym==ident) { enter(variable,ptx,lev,pdx);//填写名字表 getsymdo; } else { error(4); } return 0; } /* *输入目标代码清单 */ void listcode(int cx0) { int i; if (listswitch) { for(i=cx0;i { printf("%d %s %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a); fprintf(fa,"%d %s %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a); } } } /* *语句处理 */ int statement(bool* fsys,int * ptx,int lev) { int i,cx1,cx2; bool nxtlev[symnum]; if(sym==ident) { i=position(id,*ptx); if(i==0) { error(11); } else { if(table[i].kind!=variable) { error(12); i=0; } else { getsymdo; if(sym==becomes) { getsymdo; } else { error(13); } word域代码详解 十个特殊指令(域开关),分别是: 1.数组\A、 2.括号\B、 3. 位移\D、 4.分式\F、 5.积分\I、 6.列表\L、 7.重叠\O、 8.根号\R、 9.上下标\S、 10.框\X, 每个开关又有若干个选项,用以精确调节格式。 1. 数组开关\A(): 按行顺序将数组元素排列为多列 域代码:{EQ \a(100,2,31) } 讲解:{EQ\列表(100,2,31排成一列)} 可用参数:\al左对齐;\ac居中;\ar右对齐;\con元素排成n 列;\vsn行间增加n 磅;\hsn列间增加n磅 \al左对齐 域代码:{EQ \a\al(100,2,31)} 讲解:{EQ \列表\左对齐(100,2,31)} \ac居中 域代码:{EQ \a\ac(100,2,31) } 讲解:{EQ \列表\居中对齐(100,2,31)} \ar右对齐 域代码:{EQ \a\ar(100,2,31) } 讲解:{EQ \列表\右对齐(100,2,31)} \con元素排成n列 域代码:{EQ \a\co3(10,2,31,0,1,0,14,3,55)} 讲解:{EQ \列表\元素排成3 列(10,2,31,0,1,0,14,3,55)} \vsn 行间增加n磅 域代码:{EQ \a\co3\vs2(10,2,31,0,1,0,14,3,55)} 讲解:{EQ \列表\元素排成3列\行间增加2磅} \hsn 列间增加n磅 域代码:{EQ \a\co3\vs2\hs4(10,2,31,0,1,0,14,3,55)} 讲解:{EQ \列表\元素排成3列\行间增加2磅\列间增加4磅} 2. 括号开关\B(): 用大小适当的括号括住元素。 域代码:{EQ \b( \a(100,2,31)) } 讲解:{EQ \加括号( \数组(100,2,31))} 可用参数:左括号使用字符* \lc\*;右括号使用字符* \rc\* ;左右括号都使用字符* \bc\* \lc\* 左括号使用字符* 域代码:{EQ \b\lc\|( \a(100,2,31))} 讲解:{EQ \加括号\左括号使用字符|( \数组(100,2,31)) } \rc\* 右括号使用字符* 域代码:{EQ \b\rc\|( \a(100,2,31)) } 讲解:{EQ \加括号\右括号使用字符|( \数组(100,2,31))} \bc\* 左右括号都使用字符* 用域代码处理Word页码 一、插入基本页码 例如某份文档,当前设置为每页两栏,现在的要求是在每一栏的下面都插入相应的页码,也就是将原来的第一页设置为1、2页,第二页设置为3、4页,以此类推。简单分析一下,其实左侧栏的页码数可以由公式“当前页码×2-1”后得到,右侧栏的页码数可以由公式“当前页码×2”得到,这里以Word 2007为例进行说明,具体操作步骤如下: 第1步:切换到“页码布局”标签页,执行“分栏→两栏”命令,将当前文档拆分为两栏,至于其他的要求可以暂时取默认设置,效果如图1所示。 图1 Word 2007执行分栏(点击看大图) 第2步:切换到“插入”标签页,在“页脚”下拉菜单中选择“空白”,接下来请在需要添加页码的位置处分别画出两个文本框,右侧栏的文本框可以通过复制获得,见图2。 图2 Word 2007画出文本框(点击看大图 二、插入域代码 第3步:将光标定位在文本框中,注意此时请仍旧切换到“插入”标签页,在“文档部件”下拉菜单中选择“域”,此时会弹出图3所示的对话框,在“类别”下拉列表框中选择“等式和 公式”,在“域名”列表框中选择“= (Formula)”,记得请去除右下角的“更新时保留原格式”复选框。 图3 Word 2007插入域(点击看大图) 单击“确定”按钮,此时文本框中的文字会变为“!异常的公式结尾”,其实这并非错误,只是一行域代码而已,按下“Alt+F9”组合键后会正常显示“{ = }”原形;将光标定位在“=”的后面,继续插入“编号”中的“Page”域,注意请仍旧去除“更新时保留原格式”的复选框,插入后域代码变为“{ ={ PAGE } }”。 第4步:现在,我们应该根据事先的分析,将这个已插入的域更改为“{ ={ PAGE }*2-1 }”,接下来再按照同样的方法,将右侧栏的域代码更改为“{ ={ PAGE }*2 }”(见图4)。 图4 Word 2007修改已插入域(点击看大图) 完成上面的工作后,我们就可以按下“Alt+F9”组合键进行查看,注意请将两个文本框的“线条”的颜色设置为“无颜色”,如图5所示,效果不错吧?如果有需要的话,你可以在页码的前后分别输入“第”和“页”,如果是一页分成了三栏,那么它的域代码应该分别设置为 /*PL/0编译程序(C语言版) *编译和运行环境: *Visual C++6.0 *WinXP/7 *使用方法: *运行后输入PL/0源程序文件名 *回答是否将虚拟机代码写入文件 *回答是否将符号表写入文件 *执行成功会产生四个文件(词法分析结果.txt符号表.txt虚拟代码.txt源程序和地址.txt) */ #include 1.什么是域 简单地讲,域就是引导Word在文档中自动插入文字、图形、页码或其他信息的一组代码。每个域都有一个唯一的名字,它具有的功能与Excel中的函数非常相似。下面以Seq和Date域为例,说明有关域的一些基本概念。 形如“{Seq Identifier [Bookmark ] [Switches ]}”的关系式,在Word中称为“域代码”。它是由: 域特征字符:即包含域代码的大括号“{}”,不过它不能使用键盘直接输入,而是按下Ctrl+F9组合键输入的域特征字符。 域名称:上式中的“Seq”即被称为“Seq域”,Word 2003提供了9大类共74种域。 域指令和开关:设定域工作的指令或开关。例如上式中的“Identifier”和“Bookmark”,前者是为要编号的一系列项目指定的名称,后者可以加入书签来引用文档中其他位置的项目。“Switches”称为可选的开关,域通常有一个或多个可选的开关,开关与开关之间使用空格进行分隔。 域结果:即是域的显示结果,类似于Excel函数运算以后得到的值。例如在文档中输入域代码“{Date \@ "yyyy年m月d日" \* MergeFFormat}”的域结果是当前系统日期。 域可以在无须人工干预的条件下自动完成任务,例如编排文档页码并统计总页数;按不同格式插入日期和时间并更新;通过链接与引用在活动文档中插入其他文档;自动编制目录、关键词索引、图表目录;实现邮件的自动合并与打印;创建标准格式分数、为汉字加注拼音等等。 2.在文档中插入域 (1)使用命令插入域 在Word中,高级的复杂域功能很难用手工控制,如“自动编号”和“邮件合并”、“题注”、“交叉引用”、“索引和目录”等。为了方便用户,9大类共74种域大都以命令的方式提供。 在“插入”菜单中提供有“域”命令,它适合一般用户使用,Word提供的域都可以使用这种方法插入。你只需将光标放置到准备插入域的位置,单击“插入→域”菜单命令,即可打开“域”对话框。 首先在“类别”下拉列表中选择希望插入的域的类别,如“编号”、“等式和公式”等。选中需要的域所在的类别以后,“域名”列表框会显示该类中的所有域的名称,选中欲插入的域名(例如“AutoNum”),则“说明”框中就会显示“插入自动编号”,由此可以得知这个域的功能。对AutoNum域来说,你只要在“格式”列表中选中你需要的格式,单击“确定”按钮就可以把特定格式的自动编号插入页面。如图1所示。 你也可以选中已经输入的域代码,单击鼠标右键,然后选择“更新域”、“编辑域”或“切换域代码”命令,对域进行操作。 (2)使用键盘插入 如果你对域代码比较熟悉,或者需要引用他人设计的域代码,使用键盘直接输入会更加快捷。其操作方法是:把光标放置到需要插入域的位置,按下Ctrl+F9组合键插入域特征字符“{ }”。接着将光标移动到域特征代码中间,按从左向右的顺序输入域类型、域指令、开关等。结束后按键盘上的F9键更新域,或者按下Shift+F9组合键显示域结果。 一、插入基本页码 例如某份文档,当前设置为每页两栏,现在的要求是在每一栏的下面都插入相应的页码,也就是将原来的第一页设置为1、2页,第二页设置为3、4页,以此类推。简单分析一下,其实左侧栏的页码数可以由公式“当前页码×2-1”后得到,右侧栏的页码数可以由公式“当前页码×2”得到,这里以Word 2007为例进行说明,具体操作步骤如下: 第1步:切换到“页码布局”标签页,执行“分栏→两栏”命令,将当前文档拆分为两栏,至于其他的要求可以暂时取默认设置,效果如图1所示。 图1 Word 2007执行分栏 第2步:切换到“插入”标签页,在“页脚”下拉菜单中选择“空白”,接下来请在需要添加页码的位置处分别画出两个文本框,右侧栏的文本框可以通过复制获得,见图2。 图2 Word 2007画出文本框 二、插入域代码 第3步:将光标定位在文本框中,注意此时请仍旧切换到“插入”标签页,在“文档部件”下拉菜单中选择“域”,此时会弹出图3所示的对话框,在“类别”下拉列表框中选择“等式和公式”,在“域名”列表框中选择“= (Formula)”,记得去除右下角的“更新时保留原格式”复选框。 图3 Word 2007插入域 单击“确定”按钮,此时文本框中的文字会变为“!异常的公式结尾”,其实这并非错误,只是一行域代码而已,按下“Alt+F9”组合键后会正常显示“{ = }”原形;将光标定位在“=”的后面,继续插入“编号”中的“Page”域,注意请仍旧去除“更新时保留原格式”的复选框,插入后域代码变为“{ ={ PAGE } }”。 第4步:现在,我们应该根据事先的分析,将这个已插入的域更改为“{ ={ PAGE }*2-1 }”,接下来再按照同样的方法,将右侧栏的域代码更改为“{ ={ PAGE }*2 }”(见图4)。 图4 Word 2007修改已插入域 完成上面的工作后,我们就可以按下“Alt+F9”组合键进行查看,注意请将两个文本框的“线条”的颜色设置为“无颜色”,如图5所示,效果不错吧?如果有需要的话,你可以在页码的前后分别输入“第”和“页”,如果是一页分成了三栏,那么它的 PL/0编译器源程序分析 PL/0语言是Pascal语言的一个子集,我们这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。 PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。词法分析和代码生成作为独立的子程序供语法分析程序调用。语法分析的同时,提供了出错报告和出错恢复的功能。在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。 词法分析子程序分析: 词法分析子程序名为getsym,功能是从源程序中读出一个单词符号(token),把它的信息放入全局变量sym、id和num中,语法分析器需要单词时,直接从这三个变量中获得。(注意!语法分析器每次用完这三个变量的值就立即调用getsym子程序获取新的单词供下一次使用。而不是在需要新单词时才调用getsym过程。)getsym过程通过反复调用getch子过程从源程序过获取字符,并把它们拼成单词。getch过程中使用了行缓冲区技术以提高程序运行效率。 词法分析器的分析过程:调用getsym时,它通过getch过程从源程序中获得一个字符。如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把sym变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把sym置为ident,把这个单词存入id变量。查保留字表时使用了二分法查找以提高效率。如果getch获得的字符是数字,则继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。如果识别出其它合法的符号(比如:赋值号、大于号、小于等于号等),则把sym则成相应的类型。如果遇到不合法的字符,把sym置成nul。 语法分析子程序分析: 语法分析子程序采用了自顶向下的递归子程序法,语法分析同时也根据程序的语意生成相应的代码,并提供了出错处理的机制。语法分析主要由分程序分析过程(block)、常量定义分析过程(constdeclaration)、变量定义分析过程(vardeclaration)、语句分析过程(statement)、表达式处理过程(expression)、项处理过程(term)、因子处理过程(factor)和条件处理过程(condition)构成。这些过程在结构上构成一个嵌套的层次结构。除此之外,还有出错报告过程(error)、代码生成过程(gen)、测试单词合法性及出错恢复过程(test)、登录名字表过程(enter)、查询名字表函数(position)以及列出类PCODE代码过程(listcode)作过语法分析的辅助过程。 由PL/0的语法图可知:一个完整的PL/0程序是由分程序和句号构成的。因此,本编译程序在运行的时候,通过主程序中调用分程序处理过程block来分析分程序部分(分程序分析过程中还可能会递归调用block过程),然后,判断最后读入的符号是否为句号。如果是句号且分程序分析中未出错,则是一个合法的PL/0程序,可以运行生成的代码,否则就说明源PL/0程序是不合法的,输出出错提示即可。 下面按各语法单元分析PL/0编译程序的运行机制。 分程序处理过程: /*PL/0 编译系统C版本头文件 */ # define norw 13 ET and Visual C++.NET 2003 *WinNT, Win 200, WinXP and Win2003 *2 gcc version (Red Hat Linux Fedora core 1 *Intel 32 platform *使用方法: *运行后输入PL/0 源程序文件名 *回答是否输出虚拟机代码 *回答是否输出名字表 * 输出虚拟机代码 * 输出源文件及其各行对应的首地址 * 输出结果 * 输出名字表 */ #include<> #include"" #include"" /*解释执行时使用的栈*/ #define stacksize 500 int main() { bool nxtlev[symnum]; printf("Input pl/0 file "); scanf("%s",fname); /*输入文件名*/ fin=fopen(fname,"r"); ]=period; ssym[';']=semicolon; /*设置保留字名字,按照字母顺序,便于折半查找*/ strcpy(&(word[0][0]),"begin"); strcpy(&(word[1][0]),"call"); strcpy(&(word[2][0]),"const"); strcpy(&(word[3][0]),"do"); strcpy(&(word[4][0]),"end"); strcpy(&(word[5][0]),"if"); strcpy(&(word[6][0]),"odd"); strcpy(&(word[7][0]),"procedure"); strcpy(&(word[8][0]),"read"); strcpy(&(word[9][0]),"then"); strcpy(&(word[10][0]),"var"); strcpy(&(word[11][0]),"while"); strcpy(&(word[12][0]),"write"); /*设置保留字符号*/ wsym[0]=beginsym; wsym[1]=callsym; wsym[2]=constsym; wsym[3]=dosym; wsym[4]=endsym; wsym[5]=ifsym; wsym[6]=oddsym; wsym[7]=procsym; wsym[8]=readsym; wsym[9]=thensym; 课程设计报告 ( 2016--2017年度第一学期) 名称:编译技术课程设计 题目:PL/0语言编译器的中间代码生成院系:控制与计算机工程 班级:信安1401 学号:1141290105 学生姓名:黄竞昶 指导教师:徐欢 设计周数:一周 成绩: 日期:2016年12 月29日 1 课程设计的目的和要求 1.1 课程设计的目的 本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。 1.2 课程设计的要求 1、要求用递归子程序法/或预测分析法实现对表达式、各种说明语句、控制语句进行语法分析。 2、若语法正确,则用语法制导翻译法进行语义翻译:对说明语句,要求将说明的各符号记录到相应符号表中;对可执行语句,应产生出四元式中间代码并填写到三地址码表中; 3、若语法错误,要求指出出错性质和出错位置(行号)。出错处理应设计成一个出错处理子程序。 2 系统描述 PL/0的编译程序和目标程序的解释执行程序都是用JA V A语言书写的,因此PL/0语言可在配备JA V A语言的任何机器上实现。本次课设开发平台即为JA V A。用递归子程序法实现了对表达式、各种说明语句、控制语句进行语法的分析。其中,对各个变量符号保存到了符号表中。对可执行语句,转化成四元式中间代码进行输出。本程序中,通过出错处理子程序,也进行了语法的错误的记录,并且输出了出错的行号和出错原因。 该程序的输入是打开test文件,通过文件输入流读入,输出有生成的中间代码、符号表内容、错误分析三部分内容,分别用java界面控件显示出来。 2.1 文法的描述 在计算机科学中,文法是编译原理的基础,是描述一门程序设计语言和实现其编译器的方法。文法的描述多用BNF(巴克斯范式),而另一个重要的概念:正则表达式,也是文法的另一种形式。 PL/0文法的EBNF表示: <程序>::= <分程序>. <分程序>::= [<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句> <常量说明部分>::= const<常量定义>{,<常量定义>}; 域应用基础 1.什么是域 简单地讲,域就是引导Word在文档中自动插入文字、图形、页码或其他信息的一组代码。每个域都有一个唯一的名字,它具有的功能与Excel中的函数非常相似。下面以Seq和Date域为例,说明有关域的一些基本概念。 形如“{Seq Identifier [Bookmark ] [Switches ]}”的关系式,在Word中称为“域代码”。它是由: 域特征字符:即包含域代码的大括号“{}”,不过它不能使用键盘直接输入,而是按下Ctrl+F9组合键输入的域特征字符。 域名称:上式中的“Seq”即被称为“Seq域”,Word 2003提供了9大类共74种域。 域指令和开关:设定域工作的指令或开关。例如上式中的“Identifier”和“Bookmark”,前者是为要编号的一系列项目指定的名称,后者可以加入书签来引用文档中其他位置的项目。“Switches”称为可选的开关,域通常有一个或多个可选的开关,开关与开关之间使用空格进行分隔。 域结果:即是域的显示结果,类似于Excel函数运算以后得到的值。例如在文档中输入域代码“{Date \@ "yyyy年m月d日" \* MergeFForma t}”的域结果是当前系统日期。 域可以在无须人工干预的条件下自动完成任务,例如编排文档页码并统计总页数;按不同格式插入日期和时间并更新;通过链接与引用在活动文档中插入其他文档;自动编制目录、关键词索引、图表目录;实现邮件的自动合并与打印;创建标准格式分数、为汉字加注拼音等等。 2.在文档中插入域 (1)使用命令插入域 在Word中,高级的复杂域功能很难用手工控制,如“自动编号”和“邮件合并”、“题注”、“交叉引用”、“索引和目录”等。为了方便用户,9大类共74种域大都以命令的方式提供。 在“插入”菜单中提供有“域”命令,它适合一般用户使用,Word提供的域都可以使用这种方法插入。你只需将光标放置到准备插入域的位置,单击“插入→域”菜单命令,即可打开“域”对话框。 首先在“类别”下拉列表中选择希望插入的域的类别,如“编号”、“等式和公式”等。选中需要的域所在的类别以后,“域名”列表框会显示该类中的所有域的名称,选中欲插入的域名(例如“AutoNum”),则“说明”框中就会显示“插入自动编号”,由此可以得知这个域的功能。对AutoNum域来说,你只要在“格式”列表中选中你需要的格式,单击“确定”按钮就可以把特定格式的自动编号插入页面。如图1所示。 你也可以选中已经输入的域代码,单击鼠标右键,然后选择“更新域”、“编辑域”或“切换域代码”命令,对域进行操作。 (2)使用键盘插入 如果你对域代码比较熟悉,或者需要引用他人设计的域代码,使用键盘直接输入会更加快捷。其操作方法是:把光标放置到需要插入域的位置,按下Ctrl+F9组合键插入域特征字符“{ }”。接着将光标移动到域特征代码中间,按从左向右的顺序输入域类型、域指令、开关等。结束后按键盘上的F9键更新域,或者按下Shift+F9组合键显示域结果。 /*PL/0 编译系统C版本头文件pl0.h*/ # define norw 13 //a number of reserved word /*关键字个数*/ # define txmax 100 //length of identifier table /*名字表容量*/ # define nmax 14 //max number of digits in numbers /*number的最大位数*/ # define al 10 //length of identifier /*符号的最大长度*/ # define amax 2047 //maximum address /*地址上界*/ # define levmax 3 //max depth of block nesting /*最大允许过程嵌套声明层数[0,lexmax]*/ # define cxmax 200 //size of code array /*最多的虚拟机代码数*/ /*符号*/ enum symbol{ nul, ident, number, plus, minus, times, slash, oddsym, eql, neq, //slash斜线 lss, leq, gtr, geq, lparen, //leq :less than or equal to; gtr: great than;lparen:left parenthesis rparen, comma, semicolon,period, becomes,//comma逗号semicolon分号period句号becomes赋值号 beginsym, endsym, ifsym, thensym, whilesym, writesym, readsym, dosym, callsym, constsym, varsym, procsym, }; #define symnum 32 /*-------------*/ enum object{ //object为三种标识符的类型 constant, variable, procedur, }; /*--------------*/ enum fct{ //fct类型分别标识类PCODE的各条指令 lit, opr, lod, sto, cal, inte, jmp, jpc, //书本P23 }; #define fctnum 8 /*--------------*/ struct instruction //指令 { enum fct f; //功能码 int l; //层次差 int a; //P23 }; FILE * fas; //输出名字表 WORD EQ域汇总?? 2010-06-08 20:55:35|??分类:??|??标签:?|字号大中小?订阅 域是Word的精髓,他的应用是非常广泛的,正确使用域可以实现许多比较复杂的功能。在Word 中域共有九大类七十余种,这其中尤以EQ域变化最多最为复杂。Eq是Eq tion(公式)的缩写,Eq域能够生成数学公式。 创建公式当然最好用“公式编辑器”了,但在某些情况下使用Eq 域来输入简单的数学公式也是一个不错的选择。在这里我就给大家介绍一下EQ域的典型应用。 一、有关域的几个名词: 1、域:指导Word在文档中自动插入文字、图形、页码和其它资料的一组代码。 2、域开关:在使用域时,引发特定操作的特殊说明,一般是指添至域中用于修饰结果的选项。 3、域名:域的名称,如EQ域、TIME域等。 4、域记号:一对大括号{}。注意不能直接用键盘输入,应该用后面介绍的"插入空白域"的方法来实现。 5、域的两种显示方式:一种是以域代码方式显示,一种以域结果方式显示。以"Time"域为例,它以域代码方式显示时是这样的:{TIME \*MERGEFORMAT},它以域结果方式显示是这样的:7:03:30 PM 二、与域有关的快捷键: 1、在文档中插入空白域:按Ctrl+F9键(也可以用命令"插入→域"来实现)。 2、在域代码和域结果之间切换:按Shift+F9键。 3、更新选择的域:按F9键。 4、取消某个域的链接:先选中该域,再按Ctrl+Shift+F9键,这时域结果将以平常文本的形式显示出来。 5、转到前一个域:按Shift+F11键;转到后一个域:按F11键。 6、锁定域:按Ctrl+F11键。例如,在文档中插入Time域,在打印文档时会自动更新该域,如果希望保持插入的时间值,只要在打印之间锁定该域就可以了。解除域的锁定:按 Ctrl+Shift+F11键。 三、EQ域的10个开关及运用实例: 1、数组开关:\a() 按照行的顺序将数组元素(经笔者实验元素最多为39个)排列为多列,并可以用下列选项对\a 开关作进一步修饰: \al——列内元素左对齐。 \ar——列内元素右对齐。 \ac——列内元素居中。 \con——将元素排成n列。 \vsn——行间增加n磅的间距。 \hsn——列间增加n磅的间距。 例1:我们要在文档中输入今年10月份的月历,可以插入如下域代码:{eq \a\ac\co7\vs4\hs20(日,一,二,三,四,五, 六,,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28 ,29,30,31)},其显示结果如图1: ? Word 中的域代码列表 Word for Office 365 Word for Office 365 for Mac Word 2019 Word 2019 for Mac 更多... 注意:我们希望能够尽快以你的语言为你提供最新的帮助容。本页面是自动翻译的,可能包含语法错误或不准确之处。我们的目的是使此容能对你有所帮助。可以在本页面底部告诉我们此信息是否对你有帮助吗?请在此处查看本文的英文版本以便参考。 注意:有关插入和编辑域代码、使用开关、设置和更改属性、显示结果与域代码、锁定域和其他常见任务的详细信息, 请参阅在 Word 中插入、编辑和查看域。 在 Word 中插入、编辑和查看域 域代码可用作文档中可能会更改的数据的占位符, 并且你可以使用它们来自动处理文档的某些方面。当您使用 Word 功能 (如页码或目录) 时, 将插入域代码, 但是您可以为其他任务手动插入域代码, 例如执行计算或填充数据源中的文档容。 这些步骤适用于在 Word 中插入任何域代码。有关包含每个域的详细信息的所有域代码的列表, 请参阅Word 中的域代码列表。 插入域 1.在要插入域的位置单击。 提示:如果你知道要插入的字段的域代码, 则可以直接在文档中键入它, 但不能键入方括号字符。按 Ctrl + F9, 然后在括号中键入代码。 2.单击“插入”>“文档部件”>“域”。 3.在“域名”列表中,选择域名。 提示:您可以通过单击 "类别" 列表中的向下箭头筛选列表。 4.在 "字段属性" 下, 选择所需的任何属性或选项, 然后单击"确定"。 注意: ?若要在 "字段" 框中查看特定字段的代码, 请单击 "域代码"。对于某些字段, 默认情况下会单击此按钮。 ?若要在另一个域中嵌套某个域,请先插入外部(容器)域(上面的步骤 1 - 4)。 然后将插入点放在要插入部域的域代码,并重复上面的步骤 2 - 4。 编辑域 WORD-域和域代码 对一般WORD用户来说,域是一个高级的议题,但是如果您希望自己能够更好地驯服WORD,使它为您效劳,您就需要熟悉并掌握它。在设定文档的页眉和页脚时,加入页码域让WORD替您对页面编号;在页眉中加入文档名称域,使打印的文档显示文件名称,以便以后查找文档;在大型文档中插入目录域,好让WORD替您管理目录的编撰等等。 域的概念 域代码是由域特征字符、域类型、域指令和开关组成的字符串; 域结果是域代码所代表的信息。 域特征字符是指包围域代码的大括号“{}”,它不是从键盘上直接输入的,按 Word 域功能详细介绍 By 冰河 一、域应用基础 1.什么是域 简单地讲,域就是引导Word在文档中自动插入文字、图形、页码或其他信息的一组代码。每个域都有一个唯一的名字,它具有的功能与Excel中的函数非常相似。下面以Seq和Date域为例,说明有关域的一些基本概念。 形如“{Seq Identifier [Bookmark ] [Switches ]}”的关系式,在Word中称为“域代码”。它是由: 域特征字符:即包含域代码的大括号“{}”,不过它不能使用键盘直接输入,而是按下Ctrl+F9组合键输入的域特征字符。 域名称:上式中的“Seq”即被称为“Seq域”,Word 2003提供了9大类共74种域。 域指令和开关:设定域工作的指令或开关。例如上式中的“Identifier”和“Bookmark”,前者是为要编号的一系列项目指定的名称,后者可以加入书签来引用文档中其他位置的项目。“Switches”称为可选的开关,域通常有一个或多个可选的开关,开关与开关之间使用空格进行分隔。 域结果:即是域的显示结果,类似于Excel函数运算以后得到的值。例如在文档中输入域代码“{Date \@ "yyyy年m月d日" \* MergeFFormat}”的域结果是当前系统日期。 域可以在无须人工干预的条件下自动完成任务,例如编排文档页码并统计总页数;按不同格式插入日期和时间并更新;通过链接与引用在活动文档中插入其他文档;自动编制目录、关键词索引、图表目录;实现邮件的自动合并与打印;创建标准格式分数、为汉字加注拼音等等。 2.在文档中插入域 (1)使用命令插入域 在Word中,高级的复杂域功能很难用手工控制,如“自动编号”和“邮件合并”、“题注”、“交叉引用”、“索引和目录”等。为了方便用户,9大类共74种域大都以命令的方式提供。 在“插入”菜单中提供有“域”命令,它适合一般用户使用,Word提供的域都可以使用这种方法插入。你只需将光标放置到准备插入域的位置,单击“插入→域”菜单命令,即可打开“域”对话框。 首先在“类别”下拉列表中选择希望插入的域的类别,如“编号”、“等式和公式”等。选中需要的域所在的类别以后,“域名”列表框会显示该类中的所有域的名称,选中欲插入的域名(例如“AutoNum”),则“说明”框中就会显示“插入自动编号”,由此可以得知这个域的功能。对AutoNum域来说,你只要在“格式”列表中选中你需要的格式,单击“确定”按钮就可以把特定格式的自动编号插入页面。如图1所示。 你也可以选中已经输入的域代码,单击鼠标右键,然后选择“更新域”、“编辑域”或“切换域代码”命令,对域进行操作。 (2)使用键盘插入 如果你对域代码比较熟悉,或者需要引用他人设计的域代码,使用键盘直接输入会更加快捷。其操作方法是:把光标放置到需要插入域的位置,按下Ctrl+F9组合键插入域特征字符“{ }”。接着将光标移动到域特征代码中间,按从左向右的顺序输入域类型、域指令、开关等。结束后按键盘上的F9键更新域,或者按下Shift+F9组合键显示域结果。 如果显示的域结果不正确,你可以再次按下Shift+F9组合键切换到显示域代码状态, //A.2 C 版本 /*编译和运行环境: *1Visual C++6.0,VisualC++.NET and Visual C++.NET 2003 *WinNT, Win 200, WinXP and Win2003 *2 gcc version 3.3.2 20031022(Red Hat Linux 3.3.2-1) *Redhat Fedora core 1 *Intel 32 platform *使用方法: *运行后输入PL/0 源程序文件名 *回答是否输出虚拟机代码 *回答是否输出名字表 *fa.tmp 输出虚拟机代码 *fa1.tmp 输出源文件及其各行对应的首地址 *fa2.tmp 输出结果 *fas.tmp 输出名字表 */ #include 源代码 pl0c.h /* 关键字个数 */ #define norw 13 /* 名字表容量 */ #define txmax 100 /* 所有的add1用于定义数组 */ #define txmaxadd1 101 /* number的最大位数 */ #define nmax 14 /* 符号的最大长度 */ #define al 10 /* 地址上界 */ #define amax 2047 /* 最大允许过程嵌套声明层数 */ #define levmax 3 /* 最多的虚拟机代码数 */ #define cxmax 200 #define cxmaxadd1 201 /* 当函数中会发生fatal error时,返回-1告知调用它的函数,最终退出程序 */ #define getsymdo if(-1==getsym())return -1 #define getchdo if(-1==getch())return -1 #define testdo(a,b,c) if(-1==test(a,b,c))return -1 #define gendo(a,b,c) if(-1==gen(a,b,c))return -1 #define expressiondo(a,b,c) if(-1==expression(a,b,c))return -1 #define factordo(a,b,c) if(-1==factor(a,b,c))return -1 #define termdo(a,b,c) if(-1==term(a,b,c))return -1 #define conditiondo(a,b,c) if(-1==condition(a,b,c))return -1 #define statementdo(a,b,c) if(-1==statement(a,b,c))return -1 #define constdeclarationdo(a,b,c) if(-1==constdeclaration(a,b,c))return -1 #define vardeclarationdo(a,b,c) if(-1==vardeclaration(a,b,c))return -1 typedef enum {false,true} bool; /* 符号 */ enum symbol {nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,rparen,comma, semicolon,period,becomes,beginsym,endsym,ifsym,thensym,whilesym,writesym,readsym,dosym,calls ym,constsym,varsym,procsym}; #define symnum 32 /* 名字表中的类型 */ enum object {constant,variable,procedur}; WORD 域代码详解 我们在word 中编辑文档时,有时会经常遇到要求输入数学公式的情况。虽然简单的加、减、乘、除等运算都可在键盘上直接输入,但遇到复杂的数学公式:如积分、开方、求和等符号时,就只能利微软的office 套件中所带的工具"公式编辑器"来完成,但是在office 套件的典型安装的过程中,并没有选择这个工具,那么有没有办法可以在word 中直接输入这些符号呢?答案是肯定的,下面我们就来讲解通过word 的EQ 域的功能输入数学公式。 一、EQ 域的基本使用格式: {EQ Switches} 其中Switches 用于指定如何使用其后跟随的括号中的元素建立公式,还可以用适当的开关选项来进行修改。EQ 域的开关特别多,特别复杂,合理的组合可以产生各种各样的公式,下面我们来详细介绍各种开关的作用及使用方法及事例。 二、EQ 域的开关及选项意义 1.数组开关:\a(),可以在文档中绘制一个二维数组。还可以使用下面的选项来修改\a 开关。 \al 列内左对齐。 \ac 列内居中对齐。 \ar 列内右对齐。 \con 元素排成 n 列(默认值为 1)。 \vsn 行间增加 n 磅的垂直间距。 \hsn 列间增加 n 磅的水平间距。 示例:{ EQ \a \al \co2 \vs3 \hs3(Axy,Bxy,A,B) } 显示如下:Axy Bxy A B 2.括号开关:\b(),用括号括住单个元素。 \lc\c 左括号使用字符 c 。 \rc\c 右括号使用字符 c 。 \bc\c 左右括号都使用指定的字符 c 。 示例:{ EQ \b \bc\{ (\r(3,x)) } 显示为? ?????3x 3.位移开关:\d(),将下一个字符向左或右移动指定磅数。 \fon () 右边 n 磅。word域代码的详解
用域代码处理Word页码
编译原理(PL0编译程序源代码)
word域功能详解
巧用域代码处理WORD中页码(双页码)
PL0编译器源程序分析
PL0源代码
PL0语言编译器的中间代码生成
word域功能详解1
(完整word版)PL0源代码(C语言版)
word公式域汇总
Word 中的域代码列表(官方)
WORD-域和域代码详解
Word2003域功能详解
PL0-C语言源代码
pl0源代码
WORD域代码详解完整版