把权力意志放出来
:创造是极客唯一的属性
一、基本思路
这一节讲解语法分析器的构造。
语法分析器的核心:读取词法分析的记号流,利用上下文无关文法识别语句。
关于语句识别的具体细节:上下文无关文法的编程实现是递归下降产生式。由于绘图语言只有四种类型的语句,所以子产生式也分四种:OriginStatement、RotStatement、ScaleStatement、ForStatement,这四个产生式分别解释一种语句规则。
另外重要的是关于表达式的产生式,它解释表达式的构造规则:表达式允许出现常数、参数、运算符和函数,并且拥有运算优先级。那么就构造出五种优先级依次上升的产生式:Expression、Term、Factor、Component、Atom。
语法分析要么识别出一个合法的语句,要么报出语法错误。
二、代码实现
语法分析器头文件parse.h
#pragma once
#ifndef PARSE_H
#define PARSE_H
#include"scanner.h"
//全局变量区
struct Token token;
double Parameter;
//数据结构区
typedef double(*FuncPtr)(double);
// 表达式节点
struct ExprNode
{
enum Token_Type OpCode;//记号种类
union {
struct {
struct ExprNode *Left, *Right;
}CaseOperator;//二元运算
struct {
struct ExprNode *Child;
FuncPtr MathFuncPtr;
}CaseFunc;//函数调用
double CaseConst;//常数,绑定右值
double *CaseParmPtr;//参数T,绑定左值
}Content;
};
//函数区
void Parser(char *SrcFilePtr);//语法分析主程序
//主函数:产生式(语句级)逻辑区
void Program();
void Statement();
void OriginStatment();
void RotStatement();
void ScaleStatment();
void ForStatement();
//主函数:产生式(表达式级)逻辑区
struct ExprNode * Expression();
struct ExprNode * Term();
struct ExprNode * Factor();
struct ExprNode * Component();
struct ExprNode * Atom();
//构建语法树
struct ExprNode * MakeExprNode(enum Token_Type opcode,...);
//辅助函数
void FetchToken();
void MatchToken(enum Token_Type AToken);
void SyntaxError(int case_of);
//测试函数
void PrintSyntaxTree(struct ExprNode *root, int indent);//打印表达式的语法树
#endif
语法分析器实现文件parse.c
#include"parse.h"
//函数区
void Parser(char *SrcFilePtr) {
/*语法分析主程序:
调用词法分析器的GetToken函数(封装在FetchToken中)返回记号,
然后使用核心产生式program()对记号流进行递归下降分析,
判断记号流的结构是否符合文法规则
*/
if (!initScanner(SrcFilePtr)) {
printf("open Source File Error!\n");
return;
}
FetchToken();//返回的记号存放在全局变量token中
Program();//递归下降的核心产生式
closeScanner();
}
//主函数:产生式(语句级)逻辑区
void Program() {
while (token.type != NONTOKEN) {
//词法分析器输出NONTOKEN表示已达记号流末尾
Statement();//匹配一条语句
MatchToken(SEMICO);
}
}
void Statement() {
switch (token.type)
{
case ORIGIN:OriginStatment(); break;
case ROT:RotStatement(); break;
case SCALE:ScaleStatment(); break;
case FOR:ForStatement(); break;
default:SyntaxError(2);
}
}
void