1.1节点类设计细节
1.1.1 _Expression的种类设计
在原来的文法中,按照运算符的优先级定义了mulop、relop、addop,然后又按照这个优先级的嵌套顺序,将表达式细化为了expression、simple expression、term、factor这四类,从前往后,从复杂到简单。由于我们只定义了_Expression这一个节点类来表示表达式,所以势必得加入一些域,以区别这些不同的情况。
首先,我们引入了type域,取值情况如下:
type取值 | 描述 |
---|---|
var | 变量引用,是一个标识符,或者标识符+中括号包围的下标列表。再具体分,则可能是变量、常量、数组元素、函数名等(这个分类将在语义分析中考虑,语法分析不考虑) |
integer | 无符号整数 |
real | 浮点数 |
char | 字符常量 |
function | 函数调用 |
compound | 包含运算符的复杂表达式 |
<br />compound表示包含运算符的复杂表达式,又可以细分为很多种情况,所以用引入operationType表示运算符类型,operation表示具体的运算符是什么,取值如下:
operationType取值 | operation取值 | 描述 |
---|---|---|
relop | > | 大于 |
>= | 大于等于 | |
< | 小于 | |
<= | 小于等于 | |
<> | 不等于 | |
= | 等于 | |
mulop | * | 乘 |
/ | 除 | |
div | 整除 | |
mod | 取余 | |
and | 且 | |
addop | + | 加 |
- | 减 | |
or | 或 | |
single | minus | 取相反数 |
not | 非 | |
bracket | 在表达式两端添加括号 |
1.1.2 _VariantRerence区分是否数组
引入flag,若flag=0,则表示不带中括号包围的下标表达式,若flag=1,则表示带中括号包围的下标表达式,即数组元素的引用。
1.1.3 _Statement类之间的关系
首先_Statement是基类,_Compound、_RepeatStatement、_WhileStatement、_ForStatement、_IfStatement、_AssignStatement、_ProcedureCall均为_Statement的派生类。所有派生类的域中,涉及到语句的,均用_Statement基类的指针来表示,因为在生成AST之前并不知道具体是哪个语句。
例如_Compound类的语句列表是_Statement类指针的列表,再例如_WhileStatement循环体语句也是_Statement类指针。
这些类之间的关系可以用下面的关系图来表示。
我们在具体代码实现时,如果要用到派生类的变量或方法,需要强制类型转化为派生类,因此需要引入一个type域,表示当前语句实际上是什么派生类。
派生类 | type取值 |
---|---|
_Compound | compound |
_RepeatStatement | repeat |
_WhileStatement | while |
_ForStatement | for |
_IfStatement | if |
_AssignStatement | assign |
_ProcedureCall | procedure |
1.1.4 _Type区分是否数组
引入flag,若flag=0,表示基本类型,若flag=1,表示数组类型。
1.1.5 _FormalParameter区分是否是引用参数
引入flag,若flag=0,表示传值参数,若flag=1,表示引用参数。
1.1.6 _Constant常量定义细节
PASCAL-S在定义常量时,首先赋值号用的是等号,其次也不会指定类型,所以常量的类型需要我们自己根据读取到的常量进行判断;同时也支持用已定义的常量的取值来初始化当前定义的常量;且不支持bool类型常量。
综上,我们需要引入一个type表示常量定义的类型:
type取值 | 描述 |
---|---|
id | 由别的常量取值初始化 |
integer | 由整数初始化 |
real | 由浮点数初始化 |
char | 由字符常量初始化 |
另外,在定义时,还可以在右值前添加正负号,添加正号与不添加正负号无异,添加负号表示需要取相反数,因此引入bool类型变量isMinusShow表示常量是否取相反数。注意,isMinusShow不能表示是否是负数,当常量取值由别的常量定义时,别的常量可能本身已经是负数,再添加一个负号,就得到了一个正数。
1.1.7 不同节点类的类型区别
有一些语法成分的类型只能是基本类型,而有一些语法成分的类型还可以是数组,具体如下表所示:
语法成分 | 类型 |
---|---|
形式参数 | 基本类型 |
函数返回值 | 基本类型 |
变量 | 基本类型或数组 |
常量 | 除了boolean之外的基本类型 |
1.2 节点类定义
class _Expression
{
public:
string type;//表达式类型,"var"表示变量,"integer"表示整数,"real"表示浮点数,"char"表示常量字符
//"function"表示函数调用,"compound"表示复合表达式,
//compound有普通的二目运算符,还有"minus"、"not"、"bracket"等单目运算符
_VariantReference* variantReference;//变量或常量或数组
int intNum;//整数
float realNum;//浮点数
string strOfNum;//整数和浮点数的string表示(考虑从PASCAL-S源程序将字符串转为浮点数,再将浮点数转为字符串会带来精度问题,所以需要存下初始字符串值)
char charVal;//常量字符
_FunctionCall *functionCall;//函数调用
string operation;//具体操作符
string operationType;//操作符类型,"relop","mulop","addop","single"
_Expression *operand1,*operand2;
int lineNumber;//行号, 用表达式中最先出现的操作数的行号表示
public:
_Expression();
~_Expression();
//语义分析相关
public:
int totalIntValue;
bool totalIntValueValid;
string expressionType;//区别于type,这个值表示表达式的具体类型,即"integer"、"real"、"char"、"boolean"、"error",其中error表示表达式中包含类型不一致的操作数
};
class _FunctionCall
{
public:
pair<string,int> functionId;//函数标识符
vector<_Expression*> actualParaList;//实际参数列表,由表达式组成
public:
_FunctionCall();
~_FunctionCall();
public:
string returnType;//"integer"、"real"、"char"、"boolean"、"error",其中error表示函数标识符不存在
};
class _VariantReference
{
public:
pair<string,int> variantId;//变量或常量标识符和行号
int flag;//0表示非数组,1表示数组
vector<_Expression*> expressionList;//各维引用表达式列表
public:
_VariantReference();
~_VariantReference();
public:
int locFlag;//-1表示左值,1表示右值,0表示什么都不是 左值特判
string kind;//"array","var","constant","function call","function return reference"
string variantType;//"integer"、"real"、"char"、"boolean"、"error",其中"error"表示数组某一维下标表达式的类型不为"integer"或标识符不存在
};
class _Statement
{
public:
string type;//"compound","repeat","while","for","if","assign","procedure"
string statementType;//区别于type,取值为"void"或"error"
int lineNumber;//行号
bool isReturnStatement;//是否是返回值语句
public:
_Statement(){}
~_Statement(){}
};
class _Compound:public _Statement
{
public:
vector<_Statement*> statementList;//语句列表
//行号由begin的位置决定
public:
_Compound();
~_Compound();
};
class _RepeatStatement:public _Statement
{
public:
_Expression *condition;//条件表达式
_Statement *_do;//循环体语句
//行号由repeat的位置决定
public:
_RepeatStatement();
~_RepeatStatement();
};
class _WhileStatement:public _Statement
{
public:
_Expression *condition;//条件表达式
_Statement *_do;//循环体语句
//行号由while的位置决定
public:
_WhileStatement();
~_WhileStatement();
};
class _ForStatement:public _Statement
{
public:
pair<string,int> id;//循环变量
_Expression *start;//起始值
_Expression *end;//终止值
_Statement *_do;//循环体语句
//行号由for的位置决定
public:
_ForStatement();
~_ForStatement();
};
class _IfStatement:public _Statement
{
public:
_Expression *condition;//条件表达式
_Statement *then;//满足条件时执行的语句
_Statement *els;//不满足条件时执行的语句,如果为NULL,则没有else部分
//行号由if的位置决定
public:
_IfStatement();
~_IfStatement();
};
class _AssignStatement:public _Statement
{
public:
_VariantReference* variantReference;//左值变量
_Expression* expression;//右值表达式
//行号由赋值符号的位置决定
public:
_AssignStatement();
~_AssignStatement();
};
class _ProcedureCall:public _Statement
{
public:
pair<string,int> procedureId;//过程标识符
vector<_Expression*> actualParaList;//实际参数列表,由表达式组成
//行号由procedure名的位置决定
public:
_ProcedureCall();
~_ProcedureCall();
};
class _Type//类型
{
public:
pair<string,int> type;//基本类型及行号 "integer"、"char"、"real"、"boolean"
int flag;//0表示非数组,1表示数组
vector< pair<int,int> > arrayRangeList;//flag=1时,表示数组各维上下界
public:
_Type();
_Type(pair<string,int> _type,int _flag,vector< pair<int,int> > _arrayRangeList);
~_Type(){}
};
class _FormalParameter//形式参数
{
public:
pair<string,int> paraId;//形式参数标识符和行号
string type;//形式参数类型,形式参数一定是基本类型,所以改为string
int flag;//flag=0表示传值调用,flag=1表示引用调用
public:
_FormalParameter();
_FormalParameter(pair<string,int> _paraId,string _type,int _flag);
~_FormalParameter(){}
};
class _FunctionDefinition
{//函数/过程定义
public:
pair<string,int> functionID;//函数/过程标识符及行号
vector<_FormalParameter*> formalParaList;//形式参数列表
pair<string,int> type;//如果type.first是空串,则为过程,否则为函数,取值为"integer","real","boolean","char"四种
vector<_Constant*> constList;//常数定义列表
vector<_Variant*> variantList;//变量定义列表
_Compound* compound;
public:
_FunctionDefinition();
~_FunctionDefinition();
};
class _Variant//变量定义
{
public:
pair<string,int> variantId;//变量标识符ID及行号
_Type *type;//变量类型
public:
_Variant();
_Variant(pair<string,int> _variantId,_Type *_type);
~_Variant();
};
class _Constant//常量定义
{//常量定义的时候,右值可以是已经定义好的常量标识符
//在代码生成的时候,可以根据常量的范围对类型进行进一步的细化
public:
pair<string,int> constId;
string type;//常数类型,分为"id","integer","real","char"
pair<string,int> valueId;
char charValue;
int intValue;
float realValue;
string strOfVal;//所有常量取值的字符串表示
bool isMinusShow;
public:
_Constant(){}
~_Constant(){}
};
class _SubProgram//分程序
{
public:
vector<_Constant*> constList;//常数定义列表
vector<_Variant*> variantList;//变量定义列表
vector<_FunctionDefinition*> subprogramDefinitionList;//子程序和子函数定义列表
_Compound *compound;//主程序体
public:
_SubProgram();
~_SubProgram();
};
class _Program//程序
{
public:
pair<string,int> programId;//PASCAL程序名称标识符及行号
vector< pair<string,int> > paraList;//PASCAL程序参数列表及行号
_SubProgram* subProgram;//分程序
public:
_Program();
~_Program();
};
#endif // !ASTNODES_H