




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
本文格式为Word版,下载可任意编辑——编译原理上机报告
编译原理基础上机报告册
班级:XXXXXX学号:XXXXXXXX姓名:XXXXXX
目录
第一次上机题目:词法分析器的构造3
一、任务与目的3
1.任务3
2.目的3二、软件设计3
1.软件的总体结构与模块划分32.Java软件包的设计73.软件中关键的算法7三、测试例程设计与测试结果分析10
1.例程1102.例程211四、总结、体会及其他12其次次上机题目:语法分析器的构造13
一、任务与目的13
1.任务132.目的13二、软件设计13
1.Java软件包的设计132.适合编写递归下降子程序的文法133.表达式的语法树164.语法分析器主程序流程图195.语法分析器的递归下降子程序19三、测试例程设计与测试结果分析20
1.例程1202.例程221
3.例程322四、总结、体会及其他24附录:源代码25
一、analyser中的代码25
1.Token_Type中的代码25
2.Token中的代码253.mytokentab中的代码264.scanner2中的代码275.viewer中代码36二、
parser中的代码381.ExprNode中的代码382.parser中的代码403.parsermain中的代码52
第一次上机题目:词法分析器的构造
一、任务与目的
1.任务
词法分析器的构造一般有以下几大步骤:(1)用正规式对模式进行描述(2)由正规式构造NFA
(3)由NFA转化为DFA且最小化
(4)根据最小DFA编写程序并进行测试为函数绘图语言编写一个解释器
解释器接受用绘图语言编写的源程序,经语法和语义分析之后,将源程序所规定的图形显示在显示屏(或窗口)中。
2.目的
源程序实际上是一个字符序列,词法分析器读取该序列并根据构成规则将其转换为记号流。词法分析器至少需要完成以下几个任务:
(1)滤掉源程序中的解释和无用成分(空格、TAB等)(2)输出记号,供语法分析器使用(3)识别非法输入,并将非法输入作为出错记号提供给语法分析器,以便进行出
错处理
通过自己动手编写解释器,把握语言翻译特别是语言识别的基本方法。
二、软件设计
1.软件的总体结构与模块划分
(1)记号的设计
为了以后引用便利,笔者将记号单独写成了一个类。记号一般由类别和属性两部分组成。根据函数绘图语言的特点,为记号设计如下的类,其中记号的类别type和第一个属性lexeme是每个记号都必需有的信息,而后两个属性value和FunPtr,则分别是专门为常数和函数设计的。
需要特别注意的是,这里的lexeme笔者没有选择使用String,而是选择了StringBuffer类。由于笔者在后面的编程中发现lexeme属性在后面长度可能会改变,而String并不能符合这一特征,故将其定义为StringBuffer类。二来StringBuffer类和String类之间的转换是相当便利的。
另一个值得一提的应当是C中的函数指针,Java中为了避免指针的滥用不再采用它,但是还是提供了一些可以替代的解决方法。譬如用映射机制就替代了函数指针。
publicclassToken{publicToken_Typetype;publicStringBufferlexeme;publicdoublevalue;publicMethodFunPtr;
publicToken()throwsException
}
{}
Token(Token_Typea,Stringb,doublec,Methodd){}
type=a;
lexeme=newStringBuffer(b);value=c;FunPtr=d;
type=Token_Type.ERRTOKEN;lexeme=newStringBuffer(\value=0.0;FunPtr=null;
根据对记号的分析,可以将函数绘图语言的记号类别进行如下划分,且用枚举类型表示他们:
publicenumToken_Type{//记号的类别
ORIGIN,SCALE,ROT,IS,//保存字TO,STEP,DRAW,FOR,FROM,//保存字T,//参数
SEMICO,L_BRACKET,R_BRACKET,COMMA,//分隔符PLUS,MINUS,MUL,DIV,POWER,//运算符FUNC,//函数CONST_ID,//常数NONTOKEN,//空记号ERRTOKEN//出错记号}
(2)模式中的正规式表示
函数绘图语言的词法可用下述正规式集合表示,其中的letter和digit是辅助定义。
描述词法的正规式
Letter=[a-zA-Z]Digit=[0-9]
COMMENT=\WHITE_SPACE=(\+SEMICO=\L_BRACKET=\R_BRACKET=\
COMMA=\PLUS=\MINUS=\MUL=\DIV=\POWER=\CONST_ID=digit+(\*)?ID=letter+(letter|digit)*
//为了简单化,笔者这里符号表的组成进行了简化,规定它只能用字母组成
(3)区分记号中的符号表
符号表是一个数组,记录了所有符合ID模式的保存字、常量名、参数名和函数名等。这里由于Java中类机制,笔者只能在类中定义变量。
publicclassmytokentab{
TokenTokenTab[]=newToken[18];//切记类中要进行初始化必需在函数中mytokentab()throwsException{
TokenTab[0]=newToken(Token_Type.CONST_ID,\TokenTab[1]=newToken(Token_Type.CONST_ID,\TokenTab[2]=newToken(Token_Type.T,\
TokenTab[3]=newToken(Token_Type.FUNC,\
.getMethod(\.getMethod(\.getMethod(\.getMethod(\.getMethod(\.getMethod(\
TokenTab[4]=newToken(Token_Type.FUNC,\TokenTab[5]=newToken(Token_Type.FUNC,\TokenTab[6]=newToken(Token_Type.FUNC,\TokenTab[7]=newToken(Token_Type.FUNC,\TokenTab[8]=newToken(Token_Type.FUNC,\
TokenTab[9]=newToken(Token_Type.ORIGIN,\TokenTab[10]=newToken(Token_Type.SCALE,\TokenTab[11]=newToken(Token_Type.ROT,\TokenTab[12]=newToken(Token_Type.IS,\TokenTab[13]=newToken(Token_Type.FOR,\TokenTab[14]=newToken(Token_Type.FROM,\TokenTab[15]=newToken(Token_Type.TO,\TokenTab[16]=newToken(Token_Type.STEP,\TokenTab[17]=newToken(Token_Type.DRAW,\
}
}
(4)正规式的DFA
根据正规式和DFA的构造算法,可以得到最终的简化DFA如下图所示:
*letterletter|digitdigit.digit301digit24*/5/6-7-+|,|;|(|)(5)词法分析器的执行流程
(6)与语法分析器的接口
词法分析器提供记号给语法分析器,它们之间的关系如下图所示:
InitScanner调用返回一个记号语法分析器调用调用GetTokenCloseScanner2.Java软件包的设计
3.软件中关键的算法
为了能够在其他的函数中调用GetToken()函数,笔者将该函数定义为public。
这个函数中和C或者C++的不同之处主要在于C中unread函数的实现。为了实现字符的回退,笔者利用了java中的PushbackReader。原因笔者将在后面进行详细表达。
publicTokenGetToken()throwsException
//inordertomakeitvisible,wedefineitpublic{
Tokentoken;intChar;charch;token=newToken();//初始化为SEMICOEmptyTokenString();token.lexeme=TokenBuffer;for(;;){
}
Char=GetChar();if(Char==-1){{}
if(!isspace((char)Char)){}
break;LineNo++;
token.type=Token_Type.NONTOKEN;returntoken;ch=(char)Char;
}elseif(Char==13)
AddCharTokenString((char)Char);if(isLetter((char)Char))
//intchar之间的转换需要测试……{
for(;;){}
BackChar((char)Char);
token=JudgeKeyToken(TokenBuffer.toString());token.lexeme=TokenBuffer;returntoken;
Char=GetChar();if(isalnum((char)Char))}
AddCharTokenString((char)Char);break;else{
}elseif(isDigit((char)Char)){
for(;;){}
if((char)Char=='.'){
AddCharTokenString((char)Char);for(;;){
Char=GetChar();if(isDigit((char)Char))else
break;
AddCharTokenString((char)Char);
}
Char=GetChar();if(isDigit((char)Char))else
break;
AddCharTokenString((char)Char);
}//endofif((char)Char=='.')BackChar((char)Char);
token.type=Token_Type.CONST_ID;token.lexeme=TokenBuffer;
token.value=Double.valueOf(TokenBuffer.toString());//如此实现atof的功能returntoken;switch((char)Char){case';':
token.type=Token_Type.SEMICO;break;
token.type=Token_Type.L_BRACKET;break;
token.type=Token_Type.R_BRACKET;break;
token.type=Token_Type.COMMA;break;
token.type=Token_Type.PLUS;break;
Char=GetChar();if(Char=='-'){}
Char=GetChar();
while(Char!='\\n'BackChar((char)Char);returnGetToken();BackChar((char)Char);
token.type=Token_Type.MINUS;break;
}else{
case'(':
case')':
case',':
case'+':
case'-':
}else{
case'/':
}
if(Char=='/'){}
Char=GetChar();if((char)Char=='*'){}
token.type=Token_Type.ERRTOKEN;break;
token.type=Token_Type.POWER;break;
BackChar((char)Char);token.type=Token_Type.MUL;break;
while(Char!='\\n'BackChar((char)Char);returnGetToken();BackChar((char)Char);token.type=Token_Type.DIV;break;
}else{
case'*':
}else{
default:
}//endofswitch((char)Char)
}//endofelsereturntoken;
三、测试例程设计与测试结果分析
1.例程1
(1)测试例程设计
为了测试词法分析器是否能够正确地分析输入序列和识别记号,而由于笔者刚刚着手Java且时间有限,故只能用Java的控制台进行输入输出。
笔者可以在Java中的Run->RunConfigurations->Arguments->Programarguments中给main主函数传递参数。(2)测试结果
test1.txt文件内容如下:originis(100,pi+300);--herearenotes.
forTfrom0to120step1draw(t,-t);
在这里,笔者特意加了—行表示解释,而且其中的还用的是小写的表示符,由于根据笔者程序的设计,不仅可以调过解释,而且还可以使得程序对大小写不敏感,这样无
论是FROM,还是from,亦或FrOm,均可以被正确识别。
测试结果如下图所示:
2.例程2
(1)测试例程设计
但是在实际中,笔者发现有时文本文档不能正确地检查到.txt文件的结尾标志。故设计如下用例。且在该用例中,笔者自行设计了出错记号ERRTOKEN。(2)测试结果
test2.txt文件内容如下:lsfjlaks;
originis(100,300);--herearenotesrotis0;throwis
测试结果如下图所示:
四、总结、体会及其他
整体来说这次用Java来实现词法分析器对我来说确实存在这不小的挑战,而且我写的程序还或多或少的存在着这样或那样的瑕疵,但我收获了大量。而这收获既包括技术方面的,也包括非技术层面的。现将我的收获列举如下:
1.现在突然开始明白为什么强人能够在很短的时间内学会一种语言,并能够灵活
运用。那是由于他们目标明确。然后只看跟自己有关的部分,有侧重点,而不是胡子眉毛一起抓。
2.起初根本不知道Java终究怎么调试,可是等到会了之后,会发现其实和其他的
任何语言一样,用Java的printf,学会如何进行调试让我至少在心理上对Java不再那么的畏惧。
3.“Java中没有指针〞这句话其实是骗人的,所谓的没有,只不过是换了个名
字而已。Java的指针一般都是用类进行包装的,而指针函数则是用java.lang.reflect进行实现的。
4.C中的将预读的字符退回到文件输入流中,回退函数ungetc,在Java中我们用
了java.io.PushbackReader来进行实现。由于平日Java中用到的关于输入输出流的函数一般是java.io.InputStream、java.io.OutputStream,以及java.io.File,而至于PushbackReader之类的退回函数则用的比较少了。学习它着实费了一番力气。
5.还有对于某些.txt文件不能识别其终止标志,这个确实比较麻烦。6.词法分析中LineNo,即跟踪记号所在源文件行号,由于Java中并不识别unsigned
类型,故只得将其定义为int。
其次次上机题目:语法分析器的构造
一、任务与目的
1.任务
语法分析是语法制导翻译的基础,语法分析器是函数绘图语言解释器的核心,因此语法分析器的构造是整个解释器构造的关键。
语法分析器的构造分为两个重要步骤:规定语言的文法和根据文法编写程序。由于我们采用递归下降子程序方法,因此在文法的设计上的要求是LL(1)文法。同时语法分析时要构造出语言结构的语法树,以便于后边的语法知道翻译。具体到此绘图语言,需要构造语法树的语言结构仅限于表达式,从而为语义做铺垫。
语法分析器的任务:
(1)为句子构造语法树
(2)检查输入序列中的错误故主要的工作如下:
(1)设计函数绘图语言的文法,使其适合递归下降分析(2)设计语法树的节点,用于存放表达式的语法树
(3)设计递归下降子程序,分析句子并构造表达式的语法树(4)设计测试程序和测试用例,检验分析器是否正确
2.目的
编写一个语法分析器,不限语言
二、软件设计
1.Java软件包的设计
由于涉及到语法分析器要调用词法分析器的内容,故现将Java中的包组织如下所示:
2.适合编写递归下降子程序的文法
包含了左递归和公共左因子的文法G1如下所示:其中$代表空。
Program->StatementSEMICO|$
Statement->OriginStatement|ScaleStatement|RotStatement|ForStatementOriginStatement
->ORIGINISL_BRACKETExpressionCOMMAExpressionR_BRACKET->SCALEISL_BRACKETExpressionCOMMAExpressionR_BRACKET
ScaleStatement
RotStatement->ROTISExpressionForStatement
Expression->ExpressionPLUSTerm
|ExpressionMINUSTerm|Term
->FORTFROMExpressionTOExpressionSTEPExpression
DRAWL_BRACKETExpressionCOMMAExpressionR_BRACKET
Term->TermMULFactor
|TermDIVFactor|Factor|MINUSFactor|Component|Atom|T
|FUNCL_BRACKETExpressionR_BRACKET|L_BRACKETExpressionR_BRACKET
Factor->PLUSFactor
Component->AtomPOWERComponentAtom->CONST_ID
消除了左递归和公共左因子的文法G3如下所示:其中$代表空。
Program->StatementSEMICO|$
Statement->OriginStatement|ScaleStatement|RotStatement|ForStatementOriginStatement
->ORIGINISL_BRACKETExpressionCOMMAExpressionR_BRACKET->SCALEISL_BRACKETExpressionCOMMAExpressionR_BRACKET
ScaleStatement
RotStatement->ROTISExpressionForStatement
->FORTFROMExpressionTOExpressionSTEPExpression
DRAWL_BRACKETExpressionCOMMAExpressionR_BRACKET
Expression->TermExpression’Expression’->PLUS
Term->FactorTerm’Term’->MULFactorTerm’
|T
|FUNCL_BRACKETExpressionR_BRACKET|L_BRACKETExpressionR_BRACKET
|DIVFactorTerm’|$
|MINUSFactor|Component|Atom
|TermExpression’|MINUSTermExpression’|$
Factor->PLUSFactor
Component->AtomPOWERComponentAtom->CONST_ID
对Term进行了转换的文法G4如下所示:
Program->{StatementSEMICO}
Statement->OriginStatement|ScaleStatement|RotStatement|ForStatementOriginStatement
->ORIGINISL_BRACKETExpressionCOMMAExpressionR_BRACKET->SCALEISL_BRACKETExpressionCOMMAExpressionR_BRACKET
ScaleStatement
RotStatement->ROTISExpressionForStatement
->FORTFROMExpressionTOExpressionSTEPExpression
DRAWL_BRACKETExpressionCOMMAExpressionR_BRACKET
Expression->Term{(PLUS|MINUS)Term}Term->Factor{(MUL|DIV)Factor}Factor
|T
->PLUSFactor|MINUSFactor|Component
->AtomPOWERComponent|Atom
Component
Atom->CONST_ID
|FUNCL_BRACKETExpressionR_BRACKET
|L_BRACKETExpressionR_BRACKET
3.表达式的语法树
(1)语法树的节点
表达式的语法树的节点可以分为以下三类:
?叶节点:用于存放原子表达式,如常数或参数T。
?两个孩子的内部节点:用于存放二元运算如PlUS、MUL等构成的表达式。?一个孩子的内部节点:用于存放函数调用如sin(t)等构成的表达式。
可以用下面的一个类统一表示,根据当前记号的类别分派对应的属性,未分派到的属性为默认构造函数初始化时为其赋的值。
语法树(表达式-16+5**3/cos(T))的存储如下所示:PLUSLeftRightMINUSLeftRightDIVLeftRight
CONST_ID0.0CONST_ID16POWERLeftRightFUNCcoschildCONST_ID5CONST_ID3Tptr
parameter
在这里,Java和C不同的是不再提供类似于联合union的结构体,也就是说不再提供非此即彼的功能。本来计划使用一个类,然后将所有的属性都放在里面,用到的则进行赋值,没有用到的则不用理睬。但后来为了使条理更明了,我们对它进行了改造。在这里,我们使用了内置子类的方法。
publicclassExprNode{
publicToken_TypeOpCode;publicContentcontent;publicclassContent{
publiccaseOpCaseOperator;publiccaseFuncCaseFunc;publicdoubleCaseConst;publicDoubleCaseParmPtr;
//在初始化函数中,我们将它初始化为0//publicdouble[]CaseParmPtr=newdouble[1];//hereisveryimportant!!!!!!!!!!!!!!!!!!!!!/**
*Double类型是double的包装类,在JDK1.5以后,二者可以直接相互赋值,称为自动*看你的提醒,我推测你的jdk版本在1.5以前。假使是这样,可以用Double中的方法,
拆箱和自动装箱。
将包装类转为基本数据类型,如:double
}
publicExprNode(){}
//System.out.println(\OpCode=Token_Type.ERRTOKEN;
//System.out.println(\
//和词法分析一致,最开始初始化为Token_Type.ERRORTOKENcontent=newContent();
//System.out.println(\publicContent(){}
CaseOperator=newcaseOp();CaseFunc=newcaseFunc();CaseConst=0.0;
CaseParmPtr=newDouble(0);
publiccaseFunc(){}
child=null;MathFunPtr=null;
publicclasscaseFunc{
publicExprNodechild;publicMethodMathFunPtr;
*amount=rec.getAmount().doubleValue();***/
//我们用数组来代替指针publicclasscaseOp{
publicExprNodeLeft;publicExprNodeRight;publiccaseOp(){}
Left=null;Right=null;
}//endofclasscaseOp
}//endofclasscaseFunc
}//endofclassExprNode
(2)语法树的建立
为了简化语法树的建立过程,我们将待缺省值的函数用参数不同的重载函数来代替,通过传给函数不同类型或者个数的参数进行动态调用,而这也正是C++或者说Java与C的
不同之处。相关代码如下所示:
//生成语法树的一个节点/**
*everytime,weneedtoallocatenewnode,and*returnit!**/
//叶节点,用于存放参数T
protectedExprNodeMakeExprNode(Token_Typeopcode)//T{}
//叶节点,用于存放常数CONST_ID
protectedExprNodeMakeExprNode(Token_Typeopcode,doublevalue)//CONST_ID
//needtomodifythetypeoftoken,andthevalue.{}
//一个孩子的内部节点,用于存放函数调用
protectedExprNodeMakeExprNode(Token_Typeopcode,Methodfunc,ExprNodeexprnode)//function{}
//两个孩子的内部节点,用于存放二元运算
protectedExprNodeMakeExprNode(Token_Typeopcode,ExprNodeleft,ExprNoderight)//caseoperation
ExprNodeExprPtr=newExprNode();ExprPtr.OpCode=opcode;
ExprNodeExprPtr=newExprNode();ExprPtr.OpCode=opcode;
ExprPtr.content.CaseConst=value;returnExprPtr;
ExprNodeExprPtr=newExprNode();ExprPtr.OpCode=opcode;
ExprPtr.content.CaseParmPtr=parameter;returnExprPtr;
ExprPtr.content.CaseFunc.MathFunPtr=func;ExprPtr.content.CaseFunc.child=exprnode;returnExprPtr;
{}
ExprNodeExprPtr=newExprNode();ExprPtr.OpCode=opcode;
ExprPtr.content.CaseOperator.Left=left;ExprPtr.content.CaseOperator.Right=right;returnExprPtr;
4.语法分析器主程序流程图
5.语法分析器的递归下降子程序
首先,语法分析器以下的几个函数中需要用到词法分析为其提供的内容:publicvoidFetchToken();
publicvoidMatchToken(Token_TypeAToken);publicvoidSyntaxError(intcase_of);词法分析器为其提供的内容如下所示:函数publicGetToken();记号类型TokenType;全局变量行号intLineNo;
词法分析器、语法分析器、语义分析器三者之间的调用关系如下所示
(1)主要产生式的递归子程序
递归下降子程序分为两类,返回值为void类型的函数实现相应的产生式,返回值为ExprNode类型的函数对表达式进行语法分析的同时为其构造语法树。
产生式函数
publicvoidProgram();publicvoidStatement();publicvoidOriginStatement();publicvoidScaleStatement();publicvoidRotStatement();publicvoidForStatement();
语法树构造函数
publicExprNodeExpression();publicExprNodeTerm();publicExprNodeFactor();publicExprNodeComponent();publicExprNodeAtom();
三、测试例程设计与测试结果分析
1.例程1
(1)测试用例分析
首先,我们来做一个最简单的测试用例,用它实现语法分析器的各项基本要求。(2)测试结果
在test1.txt中内容如下:--herearenotes.
forTfrom0to120step1draw(t,-t);测试结果如下:
2.例程2
(1)测试用例分析
在这个例子中,我们着重检验我们的语法树是否正确。(2)测试结果
在test2.txt中内容如下:--herearenotes.
forTfrom0to120step1draw(t,-t);测试结果如下:
3.例程3
(1)测试用例分析
这第三个用例我们用来对词法分析器中的反射机制进行测试。而在这里,我们需要在类parser中添加下面的两个函数:
}
for(doublex=from;x
}
}
value=0.0;FunPtr=null;//FuncPtr=null;
Token(Token_Typea,Stringb,doublec,Methodd){}/*
*publicstaticvoidmain(String[]args){Tokenmytoken;mytoken=new*Token(Token_Type.NONTOKEN,\*System.out.println(mytoken.type);System.out.println(mytoken.lexeme);*System.out.println(mytoken.value);////theresultis//NONTOKEN//sfk*//34.0**}*/
type=a;
lexeme=newStringBuffer(b);value=c;FunPtr=d;
3.mytokentab中的代码
packageanalyser;
publicclassmytokentab{
TokenTokenTab[]=newToken[18];//切记类中要进行初始化必需在函数中mytokentab()throwsException
//unhandledexceptiontypeNoSuchMethodException//很重要的{
TokenTab[0]=newToken(Token_Type.CONST_ID,\TokenTab[1]=newToken(Token_Type.CONST_ID,\TokenTab[2]=newToken(Token_Type.T,\
TokenTab[3]=newToken(Token_Type.FUNC,\
.getMethod(\.getMethod(\
TokenTab[4]=newToken(Token_Type.FUNC,\
}}
TokenTab[5]=newToken(Token_Type.FUNC,\
.getMethod(\.getMethod(\.getMethod(\.getMethod(\
TokenTab[6]=newToken(Token_Type.FUNC,\TokenTab[7]=newToken(Token_Type.FUNC,\TokenTab[8]=newToken(Token_Type.FUNC,\//parametertypes
TokenTab[9]=newToken(Token_Type.ORIGIN,\TokenTab[10]=newToken(Token_Type.SCALE,\TokenTab[11]=newToken(Token_Type.ROT,\TokenTab[12]=newToken(Token_Type.IS,\TokenTab[13]=newToken(Token_Type.FOR,\TokenTab[14]=newToken(Token_Type.FROM,\TokenTab[15]=newToken(Token_Type.TO,\TokenTab[16]=newToken(Token_Type.STEP,\TokenTab[17]=newToken(Token_Type.DRAW,\
4.scanner2中的代码
packageanalyser;
//importjava.awt.List;importjava.io.*;importjava.lang.*;
//importjava.lang.Character;//importjava.awt.*;
publicclassscanner2{
staticfinalintTOKEN_LEN=100;//=100;
//staticintLineNo;publicintLineNo;//wemakeitvisible.
//如此这般,不用unsignedintStringBufferTokenBuffer;
FileReaderfr;PushbackReaderpr;//longfilePoint;F//longfileLength;
staticmytokentabtokentab;//需要初始化,必需的//???不初始化没?publicscanner2()
//inordertomakeitvisible,wesetitpublic.{}
publicintInitScanner(Stringfilename)//inordertomakeitvisible,wesetitpublic.{}
//TOKEN_LEN=100;
TokenBuffer=newStringBuffer(\//我用空串进行初始化//不能用空串进行初始化try{
fr=newFileReader(filename);pr=newPushbackReader(fr);LineNo=1;try{}
tokentab=newmytokentab();System.out.println(e.toString());}catch(Exceptione){
}catch(IOExceptionE){}
//用空串进行初始化return0;
System.out.println(E.toString());return1;
//java无析构函数
publicintCloseScanner()throwsIOException//inordertomakeitvisible,wesetispublic.{}
intGetChar()throwsIOException//该函数我们返回一个整数
//千万不要忘掉大小写转换的问题,否则不会匹配{}
inttoupper(intch){}
voidBackChar(charChar)throwsIOException{}
/*if(Char!=EOF)*/if(((int)Char)!=-1)/*
*else{System.out.println(\le!\*/
pr.unread(Char);//????pr.unread((int)Char);if(ch>='a'
ch=ch-32;intChar;Char=pr.read();/*
*if(Char==-1)System.out.println(\*/
Char=toupper(Char);returnChar;if((pr.read())!=-1){}return0;
//System.out.println(\pr.close();
voidAddCharTokenString(charChar){}
voidEmptyTokenString()//清空记号缓冲区{
intlength=TokenBuffer.length();if(length>0)
//TokenBuffer.delete(0,length-1);TokenBuffer=null;
//System.out.print(\//System.out.println((int)Char);//貌似TokenBuffer=null有点严重了~~//故需要重新new一个if(TokenBuffer==null)
TokenBuffer=newStringBuffer(\intTokenLength=TokenBuffer.length();if(TokenLength+1>=100)
return;
//在此对字符串长度进行了限制。//???else
TokenBuffer.append(Char);//我们进行如此追加/*
*if(TokenBuffer!=null){System.out.print(TokenBuffer.toString());*System.out.println(\*/
//???
//TokenBuffer..replace(0,TOKEN_LEN-1,\//必需进行完全地清理/*
*if(TokenBuffer.length()>0)
*TokenBuffer.delete(0,TokenBuffer.length()-1);*/
//清空字符缓冲区:/***
*StringBuffersb=newStringBuffer(\*
*sb.delete(0,sb.length-1);或者:sb.replace(0,sb.length-1,\
}
*/
TokenJudgeKeyToken(StringIDString)throwsException{}
publicTokenGetToken()throwsException//inordertomakeitvisible,wedefineitpublic{
Tokentoken;intChar;charch;
token=newToken();//初始化为SEMICOEmptyTokenString();/*
*System.out.print(\*System.out.println(\intloop;
for(loop=0;loop='0'returntrue;
if((ch>='a'returntrue;
}
parameter=newDouble(0);//here...wecanuseitasapointer
//andthesetis0atthebeginning.//token=newToken();
//herearesomeprivatefunctions.privatevoidenter(Stringx){}
privatevoidback(Stringx){}
privatevoidcall_match(Stringx)
//herewechangetoString,notToken_Type,because^//wemaywanttoprintthe'('{}
//树的痕迹??
//其中只调用了一个函数,那便是PrintSyntaxTreeprivatevoidTree_trace(ExprNodex){}
protectedvoidFetchToken()throwsException{}
protectedvoidMatchToken(Token_TypeThe_Token)throwsException
token=myscanner.GetToken();//itmaythrowexception
if(token.type==Token_Type.ERRTOKEN)
SyntaxError(1);PrintSyntaxTree(x,1);
System.out.println(\//?????
//System.out.println(\System.out.println(\System.out.println(\return;
{}
privatevoidSyntaxError(intcase_of){}
privatevoidErrMsg(intno,Stringmessage,StringBufferstring)//wechangeunsignedinttoint.{}
//先序遍历并打印表达式的语法树publicvoidPrintSyntaxTree(ExprNoderoot,intindent)//here^^
//weprintourgrammertree.{
inttemp;
for(temp=1;temp
}
MatchToken(Token_Type.R_BRACKET);call_match(\back(\return;
//RotStatement的递归子程序protectedvoidRotStatement()throwsException//theRotStatementis://ROTISdouble.{}
//ForStatement的递归子程序protectedvoidForStatement()throwsException//theForStatementis:
//FORtFROMdoubleTOdoubleSTEPdouble//DRAW(double,double){
ExprNodestart_ptr=newExprNode();ExprNodeend_ptr=newExprNode();ExprNodestep_ptr=newExprNode();ExprNodex_ptr=newExprNode();ExprNodey_ptr=newExprNode();//?????????????????????
enter(\
MatchToken(Token_Type.FOR);call_match(\MatchToken(Token_Type.T);call_match(\
MatchToken(Token_Type.FROM);call_match(\start_ptr=Expression();
MatchToken(Token_Type.TO);call_match(\
end_ptr=Expression();
ExprNodetmp=newExprNode();
enter(\
MatchToken(Token_Type.ROT);call_match(\
MatchToken(Token_Type.IS);call_match(\tmp=Expression();back(\return;
}
MatchToken(Token_Type.STEP);call_match(\step_ptr=Expression();
MatchToken(Token_Type.DRAW);call_match(\
MatchToken(Token_Type.L_BRACKET);call_match(\x_ptr=Expression();
MatchToken(Token_Type.COMMA);call_match(\y_ptr=Expression();
MatchToken(Token_Type.R_BRACKET);call_match(\back(\return;
//Expression的递归子程序protectedExprNodeExpression()throwsException{}
//Term的递归子程序protectedExprNodeTerm()throwsException{
ExprNodeleft=newExprNode();ExprNoderight=newExprNode();Token_Typetoken_tmp;ExprNodeleft=newExprNode();ExprNoderight=newExprNode();Token_Typetoken_tmp;
enter(\left=Term();
while(token.type==Token_Type.PLUS||token.type==Token_Type.MINUS){}
Tree_trace(left);
//System.out.println(\back(\
returnleft;
token_tmp=token.type;MatchToken(token_tmp);right=Term();
left=MakeExprNode(token_tmp,left,right);
//System.out.println(\
}
//System.out.println(\left=Factor();
//System.out.println(\
while(token.type==Token_Type.MUL||token.type==Token_Type.DIV){}
returnleft;
token_tmp=token.type;MatchToken(token_tmp);right=Factor();
left=MakeExprNode(token_t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论