0.简介
先从比较简单的语法解析开始,CScript打算设计成强类型语言,所以所有变量都要先声明才可以使用。
1.声明语句
增添了AST树
class AstNode
{
public:
int line, column;
AstNode() {};
AstNode(int _line, int _column) :line(_line), column(_column) {}
//分析语法后生成中间码
virtual operand evaluation(std::vector<Quaternion>& context, Memory& memory, NameTable& table) { return operand(); }
~AstNode() {};
};
//表达式基类
class Expression : public AstNode
{
//在上下文寻找变量
public:
Expression(int _line, int _column) :AstNode(_line, _column) {}
virtual operand evaluation(std::vector<Quaternion>& context, Memory& memory, NameTable& table) { return operand(); }
~Expression() {}
};
//语句
class Statement : public AstNode
{
public:
Statement(int _line, int _column) :AstNode(_line, _column) {}
virtual operand evaluation(std::vector<Quaternion>& context, Memory& memory, NameTable& table) { return operand(); }
~Statement() {}
};
声明了表达式和语句连个类,都是AST节点,下面将声明语句类设计好。
//变量声明语句
class VariableDeclareStatement : public Statement
{
public:
VariableDeclareStatement(int _line, int _column) :Statement(_line, _column) {}
//类型
Token type;
//类型名字
std::string typeName;
//标识符表达式
std::string identName;
//表达式解析
virtual operand evaluation(std::vector<Quaternion>& context, Memory& memory, NameTable& table) { return operand(); }
~VariableDeclareStatement() {}
};
声明语句中存储了变量类型,标识符名字,类型名字,这里的类型名字是以后有自定义类型时候使用的字段,表达式解析函数这里先不用管。
在Parser类中添加了一下几个函数来支持变量声明语法。
//语法入口
std::shared_ptr<Statement> parseStatement();
//声明表达式
std::shared_ptr<Statement> decalreStatement();
//变量声明
std::shared_ptr<VariableDeclareStatement> variableDeclare();
std::shared_ptr<Statement> Parser::parseStatement()
{
std::shared_ptr<Statement> result;
switch (getToken())
{
case KW_BOOL:
result = decalreStatement();
break;
default:
break;
}
return result;
}
语法入口函数要根据第一个token类型判断这句话属于什么语句,这里目前只写了一个bool类型声明。
下面的函数是声明表达式,因为后面还有函数声明,数组是声明等,所以需要这个函数来判断声明类型。
std::shared_ptr<Statement> Parser::decalreStatement()
{
return variableDeclare();
}
最后,根据语法结构,来识别声明语句。
std::shared_ptr<VariableDeclareStatement> Parser::variableDeclare()
{
auto result = std::make_shared<VariableDeclareStatement>(line,column);
//获取类型,类型名字
result->type = getToken();
result->typeName = getLexeme();
//吃掉类型token
pushNextToken();
//获取标识符
result->identName = getLexeme();
return result;
}
3.详情
具体代码请看源码链接,在这里