📄 parser.cpp
字号:
// ----------------------------- parser.cpp ---------------------------------
// 语法分析器类的定义
#include "parser.h"
// ------------------------ 通过词法分析器接口get_token获取一个记号
void parser_class::fetch_token()
{
token = Scanner.get_token () ;
if (token.type == ERRTOKEN) syntax_error(1);
}
// ------------------------ 匹配记号
void parser_class::match_token (enum token_type the_token)
{
if (token.type != the_token) syntax_error(2);
fetch_token();
}
// ------------------------ 语法错误处理
void parser_class::syntax_error (int case_of)
{
switch(case_of)
{ case 1: error_msg (Scanner.line_no," 非法记号 ", token.lexeme) ;
break;
case 2: error_msg (Scanner.line_no, token.lexeme, " 不是预期记号") ;
break;
}
}
// ------------------------ 打印错误信息
void parser_class::error_msg(int line, char *descrip, char *string)
{
cout << "Line No " << line << ": " << descrip << string << endl;
Scanner.close_scanner();
exit(1);
}
// ------------------------ 先序遍历并打印表达式的语法树
void parser_class::print_syntax_tree(tree_node_ptr root, int indent)
{
int temp;
for (temp=1; temp<=indent; temp++) cout << " "; // 缩进
switch(root->op_code) // 打印根节点
{ case PLUS: cout << "+" << endl; break;
case MINUS: cout << "-" << endl; break;
case MUL: cout << "*" << endl; break;
case DIV: cout << "/" << endl; break;
case POWER: cout << "**" << endl; break;
case FUNC: cout << root->content.tag_func.math_func_ptr << endl; break;
case CONST_ID: cout <<root->content.tag_const << endl; break;
case T: cout << "T" << endl; break;
default: cout << "非法的树节点!" << endl; exit(0);
}
if(root->op_code == CONST_ID || root->op_code == T) return; // 叶子节点返回
if(root->op_code == FUNC) // 递归打印一个孩子的节点
print_syntax_tree(root->content.tag_func.child,indent+1);
else // 递归打印两个孩子的节点
{ print_syntax_tree(root->content.tag_op.left, indent+1);
print_syntax_tree(root->content.tag_op.right, indent+1);
}
}
// ------------------------ 绘图语言解释器入口(与主程序的外部接口)
void parser_class::parser(char * file_name)
{
enter("parser");
if(!(Scanner.init_scanner(file_name))) // 初始化词法分析器
{ cout << "打开文件错误 !" << endl;
return;
}
fetch_token(); // 获取第一个记号
program(); // 递归下降分析
Scanner.close_scanner(); // 关闭词法分析器
back("parser");
return;
}
// ------------------------ program 的递归子程序
void parser_class::program ()
{
enter("program");
while (token.type != NONTOKEN)
{ statement();
match_token(SEMICO) ;
}
back("program");
}
// ------------------------ statement 的递归子程序
void parser_class::statement()
{
enter("statement");
switch (token.type)
{ case ORIGIN : origin_statement(); break;
case SCALE : scale_statement(); break;
case ROT : rot_statement(); break;
case FOR : for_statement(); break;
case COLOR : color_statement(); break;
default : syntax_error(2);
}
back("statement");
}
// ------------------------ origin_statement 的递归子程序
void parser_class::origin_statement()
{
enter("origin_statement");
call_match("ORIGIN"); match_token (ORIGIN);
call_match("IS"); match_token (IS);
call_match("("); match_token (L_BRACKET);
x_ptr = expression();
call_match(","); match_token (COMMA);
y_ptr = expression();
call_match(")"); match_token (R_BRACKET);
back("origin_statement");
}
// ------------------------ scale_statement 的递归子程序
void parser_class::scale_statement ()
{
enter("scale_statement");
call_match("SCALE"); match_token (SCALE);
call_match("IS"); match_token (IS);
call_match("("); match_token (L_BRACKET);
x_ptr = expression();
call_match(","); match_token (COMMA);
y_ptr = expression();
call_match(")"); match_token (R_BRACKET);
back("scale_statement");
}
// ------------------------ rot_statement 的递归子程序
void parser_class::rot_statement ()
{
enter("rot_statement");
call_match("ROT"); match_token (ROT);
call_match("IS"); match_token (IS);
angle_ptr = expression();
back("rot_statement");
}
// ------------------------ color_statement 的递归子程序
void parser_class::color_statement ()
{
enter("color_statement");
match_token (COLOR);
match_token (IS);
colors();
back("color_statement");
}
// ------------------------ color_statement 的递归子程序
void parser_class::colors()
{
enter("colors");
// printf("red=%d, black=%d, token_type=%d\n", RED, BLACK, token.type);
if (token.type==RED) line_color = red_color;
else if (token.type==BLACK) line_color = black_color;
else syntax_error(2);
// printf("black_color=%d, red_color=%d, line_color=%d\n", black_color, red_color, line_color);
match_token (token.type);
back("colors");
}
// ------------------------ for_statement 的递归子程序
void parser_class::for_statement ()
{
enter("for_statement");
call_match("FOR"); match_token (FOR);
call_match("T"); match_token(T);
call_match("FROM"); match_token (FROM);
start_ptr = expression(); // 构造参数起始表达式语法树
call_match("TO"); match_token (TO);
end_ptr = expression(); // 构造参数终结表达式语法树
call_match("STEP"); match_token (STEP);
step_ptr = expression(); // 构造参数步长表达式语法树
call_match("DRAW"); match_token (DRAW);
call_match("("); match_token (L_BRACKET);
x_ptr = expression(); // 构造横坐标表达式语法树
call_match(","); match_token (COMMA);
y_ptr = expression(); // 构造纵坐标表达式语法树
call_match(")"); match_token (R_BRACKET);
back("for_statement");
}
// ------------------------ expression 的递归子程序
tree_node_ptr parser_class::expression()
{
tree_node_ptr left, right; // 左右子树节点的指针
token_type token_tmp; // 当前记号
enter("expression");
left = term(); // 分析左操作数且得到其语法树
while (token.type==PLUS || token.type==MINUS)
{ token_tmp = token.type;
match_token(token_tmp);
right = term(); // 分析右操作数且得到其语法树
left = make_tree_node(token_tmp, left, right);
// 构造运算的语法树,结果为左子树
}
tree_trace(left); // 打印表达式的语法树
back("expression");
return left; // 返回最终表达式的语法树
}
// ------------------------ term 的递归子程序
tree_node_ptr parser_class::term()
{
tree_node_ptr left, right;
token_type token_tmp;
left = factor();
while (token.type==MUL || token.type==DIV)
{ token_tmp = token.type;
match_token(token_tmp);
right = factor();
left = make_tree_node(token_tmp, left, right);
}
return left;
}
// ------------------------ factor 的递归子程序
tree_node_ptr parser_class::factor ()
{
tree_node_ptr left, right;
if(token.type == PLUS) // 匹配一元加运算
{ match_token(PLUS);
right = factor(); // 表达式退化为仅有右操作数的表达式
}
else if(token.type == MINUS) // 匹配一元减运算
{ match_token(MINUS); // 表达式转化为二元减运算的表达式
right = factor();
left = new tree_node;
left->op_code = CONST_ID;
left->content.tag_const = 0.0;
right = make_tree_node(MINUS, left, right);
}
else right = component(); // 匹配非终结符component
return right;
}
// ------------------------ component 的递归子程序
tree_node_ptr parser_class::component()
{
tree_node_ptr left, right;
left = atom();
if(token.type == POWER)
{ match_token(POWER);
right = component(); // 递归调用component以实现POWER的右结合性质
left = make_tree_node(POWER, left, right);
}
return left;
}
// ------------------------ atom 的递归子程序
tree_node_ptr parser_class::atom()
{
struct token_rec t=token;
tree_node_ptr t_ptr, tmp;
switch (token.type)
{ case CONST_ID :
match_token (CONST_ID) ;
t_ptr = make_tree_node(CONST_ID,t.value);
break;
case T:
match_token(T);
t_ptr = make_tree_node(T);
break;
case FUNC :
match_token (FUNC);
match_token (L_BRACKET);
tmp = expression ();
t_ptr = make_tree_node(FUNC,t.func_ptr,tmp);
match_token (R_BRACKET);
break ;
case L_BRACKET :
match_token (L_BRACKET);
t_ptr = expression ();
match_token (R_BRACKET);
break ;
default :
syntax_error (2);
}
return t_ptr;
}
// ----------------- 生成语法树的一个节点
tree_node_ptr parser_class::make_tree_node(enum token_type opcode, ...)
{
tree_node_ptr t_ptr = new (struct tree_node); // 分配节点存储空间
t_ptr->op_code = opcode; // 接收记号的类别
va_list arg_ptr ;
va_start (arg_ptr, opcode);
switch(opcode) // 根据记号的类别构造不同的节点
{ case CONST_ID: // 常数节点
t_ptr->content.tag_const = (double)va_arg(arg_ptr, double);
break;
case T: // 参数节点
t_ptr->content.tag_parameter = ¶meter;
break;
case FUNC: // 函数调用节点
t_ptr->content.tag_func.math_func_ptr = (func_ptr)va_arg(arg_ptr, func_ptr);
t_ptr->content.tag_func.child
= tree_node_ptr va_arg (arg_ptr, tree_node_ptr);
break;
default: // 二元运算节点
t_ptr->content.tag_op.left
= tree_node_ptr va_arg (arg_ptr, tree_node_ptr);
t_ptr->content.tag_op.right
= tree_node_ptr va_arg (arg_ptr, tree_node_ptr);
break;
}
va_end(arg_ptr);
return t_ptr;
}
// ---------------------- 用于语法分析器中的跟踪调试
void parser_class::enter(char * x) { cout << "enter in " << x << endl; }
void parser_class::back(char * x) { cout << "exit from " << x << endl; }
void parser_class::call_match(char * x) { cout << "matchtoken " << x << endl; }
void parser_class::tree_trace(tree_node_ptr x) { print_syntax_tree(x, 1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -