行求,不多说话,开干
从bison开始
咱们先定义语言要用到的几种数据类型
typedef struct YYSTYPE
{
string vSTRING; //字符串类型
int vINTEGER;//整数类型
double vDOUBLE;//double类型
struct CompileStruct* vCompileStruct;//编译结构
Statement* vStatement;//语法结构
} YYSTYPE;
够了,就这几种就可以了,以上类型除了定义语言中需要用的类型,这些类还要提供bison的使用类型,例如定义个函数名,就需要用的vstring类型,以上最重要的是vStatement类型,它是所有表达式,语法结构的基础类型,不管是任何表达式,在menthol解析中,都会定义为statement类型
先看在整个menthol中会用到的token
%token <vSTRING>VARIDENTIFIER
%token <vSTRING> IDENTIFIER
%token <vSTRING> GLOBALVARIDENTIFIER
%token <vINTEGER>NUMBER
%token <vSTRING>STRING
%token <vDOUBLE>DOUBLE
%token <vINTEGER>TRUE_KEYWORD
%token <vINTEGER>FALSE_KEYWORD
%token IF ELSE FOR BREAK TRY EXCEPT THROW IMPORT MODULE USE
%token CONTINUE RETURN WHILE NULL_KEYWORD
%token POWER_OP NEQ_OP OR_OP AND_OP GE_OP LE_OP EQ_OP
%token ADD_ASSIGN SUB_ASSIGN DIV_ASSIGN MUL_ASSIGN ASSIGN_ASSIGN
%token MOD_ASSIGN AND_ASSIGN OR_ASSIGN XOR_ASSIGN
%token SHIFT_LEFT_OP SHIFT_RIGHT_OP WMAIN DEF VAR IN ARRAYSECTION DICT_OP TYPEOF CONST MMRT
从IF开始应为都是已经定要的常量字符串,所以只要标记就好,前8行都是需要定义类型的
关于Statement
这是语法解析中最重要的部分,他是所有表达是的基础类型,所有的表达是不管是if,while,for他们都是Statement 的子类型,定义如下
//Parser.h
class Statement
{
public:
virtual void CreateCode()=0;
virtual void AddChilder(Statement* s){}
virtual void Release()=0;
NodeType NType;
Statement():ParentNode(0),bytenumber(0),startipi(0),endipi(0),ilength(0){}
Statement* ParentNode;
int wfileaddressline;
int bytenumber;
string name;
int startipi;
int endipi;
int ilength;
};
上述代码可以看到,有两个纯虚函数,CreateCode是每一个表达是按照各自逻辑所需要生成的代码,AddChilder,是虚函数,应为有些表达式,是有子表达式的,例如module内的内容,就是module表达式的子表达式,有些是没有的,例如定义一个var $a;这种没有任何东西,也就没有子表达式,
NodeType,表示当前的表达式是什么类型表达式,类似IF,WHILE,FOR这些,它的定义如下
enum NodeType{
MNT_FunctionParameter,//函数参数
MNT_FunctionParameterWithDefault,//有默认值的函数参数
MNT_TryParameter,//try
MNT_VarIdentIfier,//$ 局部变量
MNT_FunctionParameterStatement,//函数参数集合
MNT_ExpressionStatement,
MNT_ExpressionList,
MNT_AssignmentDefinition,
MNT_InitializationDefinition,
MNT_AssignmentList,
MNT_InitializationExpression,
MNT_InitializationList,
MNT_BuiltinTypeDeclare,
MNT_ArithmeticExpressionDefinition,
MNT_IfStatement,
MNT_WhileStatement,
MNT_ForStatement,
MNT_ArrayDeclare,
MNT_DictDeclare,
MNT_ArrayElement,
MNT_DictElement,
MNT_ContinueExpression,
MNT_BreakExpression,
MNT_FunctionDefinition,
MNT_ReturnExpression,//return
MNT_TryStatement,
MNT_ThrowExpression,
MNT_CodeBlockStatement,
MNT_ImportPackageExpression,
MNT_ModuleExpresson,
MNT_ModuleFunCall,//执行函数
MNT_ModuleFunctionDefinition,//模块内函数定义
MNT_TernaryExpression,//三元表达式
MNT_DictExpression,//
MNT_FunctionCall,
MNT_FunctionArguments,
MNT_LogiceEpressionDefintion,
MNT_MinusExpression,
MNT_PlusExpression,
MNT_Release,
MNT_InverterExpression,
MNT_TypeOfExpression,
MNT_ModuleStatementList,
MNT_ModuleDefine,//模块定义
MNT_MainFunction,//main函数
MNT_InstanceExpression
};
它的作用在与判断有些表达式是否合法,例如,break就不能出现在除了while,for以外的地方
我们先举个例子来说明Statement的用法,先看while的bison定义
while_statement: WHILE '(' expression_definition ')' funciton_codeblock_statement
{
$$ = new WhileStatement();
$$->AddChilder($3);
$$->AddChilder($5);
}
;
解析它的程序定义如下
class WhileStatement:public Statement{
public:
WhileStatement();//构造
~WhileStatement();
void AddChilder(Statement* s);//用于往Member成员中加入子表达式
void CreateCode();//生成代码的方式
int GetJmpPostion();
int GetTemplateid();
void SetBreakPostion(int b);
void Release();
private:
vector <Statement*> *Member;//子成员,两个expression_definition,funciton_codeblock_statement
int postion1;
int postion2;
int templateid;
vector<int> *breakpostionvector;
};
其他的额例如if,for,module等表达式,他们的基本定义也差球不多。
这个过程会把所有的以Statement为基类的表达式按层级关系,加入到statementlist类中一个叫
CompileStructTable的变量里
vector <Statement*> *CompileStructTable;
在所有程序解析完以后,调用StatementList::CreateCode,这个会调用所有表达式子类型中CreateCode方法,生成编译后的汇编(程序定义的类似汇编的语法),然后按一定的格式存储在文件中,这个文件的存储,会在以后讲
现在从bison开始看起
1.VARIDENTIFIER,这个是定义例如参数名、变量名称这些的
VARIDENTIFIER{
$$ =new VarIdentIfier($1);
}
当遇到VARIDENTIFIER,也就是lex中以$开头的变量,会把变量名当参数出入
VarIdentIfier 构造函数中
//Parser.cpp
VarIdentIfier::VarIdentIfier(string s){
wfileaddressline = lineno;
name = s;
NType = MNT_VarIdentIfier;
}
IDENTIFIER {
StatementList *ls = (StatementList*)parm;
ls->AddStringConstant(string($1));
BuiltinTypeDeclare* btd =new BuiltinTypeDeclare();
btd->SetFunctionPointerOrModule($1,1);
$$= btd;
}
2.IDENTIFIER,这个用的地方比较多,例如用来表示函数名称,包的名称,属性名称等
例如在导入一个包的时候
import aaa
aaa就是定义为IDENTIFIER
3.GLOBALVARIDENTIFIER,这个是用来定义模块中以@开头的全局变量的
//bison.y
GLOBALVARIDENTIFIER{
StatementList *ls = (StatementList*)parm;
ls->AddStringConstant(string($1));
$$ = new VarIdentIfier((char*)$1.c_str());}
;
当bison被解析的时候,解析程序会和定义VARIDENTIFIER一样,但多了一步,会将全局变量名称当作字符串存入程序的数据段中作为固定数据保存,这样做的原因是在虚拟机中,程序运行时可以动态判断出模块是否具有某个全局变量
有了上面上面的基础,就可以开始一步步解析语法了
不想写了,下一节开始讲表达式解析