基于第二章的词法分析程序,使用C/C++语言编写PL/0编译程序的语法分析程序。
时间: 2024-05-03 09:18:45 浏览: 319
PL/0语法分析程序
PL/0语法分析程序的主要任务是将词法分析器生成的记号流转化为语法树,同时检查程序是否符合语法规则。以下是一个基于递归下降分析法的PL/0语法分析程序的实现:
```c++
#include <iostream>
#include <vector>
#include "lexer.h"
using namespace std;
// 语法树节点类型
enum class NodeType {
Program, ConstDecl, VarDecl, ProcDecl, Statement, Expression
};
// 语法树节点
struct Node {
NodeType type;
string name; // 标识符名称
int value; // 常量值或变量地址
vector<Node*> children;
};
// 词法分析器
Lexer lexer("source_code.txt");
// 当前记号
Token current_token;
// 错误信息
string error_msg;
// 向前读取一个记号
void next_token() {
current_token = lexer.get_token();
}
// 报告错误
void report_error(const string& msg) {
error_msg = "Error: " + msg + ", at line " + to_string(current_token.line_no) + ".";
}
// 匹配记号
bool match(TokenType expected_type) {
if (current_token.type == expected_type) {
next_token();
return true;
}
return false;
}
// 构造语法树节点
Node* new_node(NodeType type, const string& name = "", int value = 0) {
Node* node = new Node;
node->type = type;
node->name = name;
node->value = value;
return node;
}
// 程序
Node* program();
// 常量声明
Node* const_decl();
// 变量声明
Node* var_decl();
// 过程声明
Node* proc_decl();
// 语句
Node* statement();
// 表达式
Node* expression();
// 因子
Node* factor();
// 项
Node* term();
// 获得标识符的地址
int get_address(const string& name) {
// TODO: 实现符号表
return 0;
}
// 程序
Node* program() {
Node* node = new_node(NodeType::Program);
if (match(TK_CONST)) {
node->children.push_back(const_decl());
}
if (match(TK_VAR)) {
node->children.push_back(var_decl());
}
while (current_token.type == TK_PROCEDURE) {
node->children.push_back(proc_decl());
}
node->children.push_back(statement());
if (current_token.type != TK_PERIOD) {
report_error("Missing period");
}
return node;
}
// 常量声明
Node* const_decl() {
Node* node = new_node(NodeType::ConstDecl);
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
if (match(TK_EQUAL)) {
if (match(TK_NUMBER)) {
node->value = stoi(current_token.lexeme);
if (match(TK_SEMICOLON)) {
return node;
}
}
}
}
report_error("Invalid const declaration");
return nullptr;
}
// 变量声明
Node* var_decl() {
Node* node = new_node(NodeType::VarDecl);
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
if (match(TK_SEMICOLON)) {
return node;
}
}
report_error("Invalid var declaration");
return nullptr;
}
// 过程声明
Node* proc_decl() {
Node* node = new_node(NodeType::ProcDecl);
if (match(TK_PROCEDURE)) {
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
if (match(TK_SEMICOLON)) {
node->children.push_back(statement());
if (match(TK_SEMICOLON)) {
return node;
}
}
}
}
report_error("Invalid procedure declaration");
return nullptr;
}
// 语句
Node* statement() {
Node* node = new_node(NodeType::Statement);
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
if (match(TK_ASSIGN)) {
node->children.push_back(expression());
node->value = get_address(node->name);
if (node->value == 0) {
report_error("Undefined variable: " + node->name);
}
return node;
}
}
else if (match(TK_CALL)) {
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
return node;
}
}
else if (match(TK_BEGIN)) {
while (true) {
node->children.push_back(statement());
if (!match(TK_SEMICOLON)) {
break;
}
}
if (match(TK_END)) {
return node;
}
}
else if (match(TK_IF)) {
node->children.push_back(expression());
if (match(TK_THEN)) {
node->children.push_back(statement());
return node;
}
}
else if (match(TK_WHILE)) {
node->children.push_back(expression());
if (match(TK_DO)) {
node->children.push_back(statement());
return node;
}
}
else if (match(TK_READ)) {
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
node->value = get_address(node->name);
if (node->value == 0) {
report_error("Undefined variable: " + node->name);
}
return node;
}
}
else if (match(TK_WRITE)) {
node->children.push_back(expression());
return node;
}
return nullptr;
}
// 表达式
Node* expression() {
Node* node = new_node(NodeType::Expression);
if (match(TK_PLUS) || match(TK_MINUS)) {
node->children.push_back(new_node(NodeType::Expression, "", 0));
}
node->children.push_back(term());
while (current_token.type == TK_PLUS || current_token.type == TK_MINUS) {
Token op = current_token;
node->children.push_back(new_node(NodeType::Expression, "", 0));
next_token();
node->children.back()->children.push_back(node->children.back());
node->children.back()->children.push_back(term());
node->children.back()->name = op.lexeme;
}
return node;
}
// 因子
Node* factor() {
Node* node = new_node(NodeType::Expression);
if (match(TK_IDENTIFIER)) {
node->name = current_token.lexeme;
node->value = get_address(node->name);
if (node->value == 0) {
report_error("Undefined variable: " + node->name);
}
}
else if (match(TK_NUMBER)) {
node->value = stoi(current_token.lexeme);
}
else if (match(TK_LPAREN)) {
node = expression();
if (!match(TK_RPAREN)) {
report_error("Missing right parenthesis");
}
}
else {
report_error("Invalid factor");
return nullptr;
}
return node;
}
// 项
Node* term() {
Node* node = factor();
while (current_token.type == TK_TIMES || current_token.type == TK_SLASH) {
Token op = current_token;
node->children.push_back(new_node(NodeType::Expression, "", 0));
next_token();
node->children.back()->children.push_back(node->children.back());
node->children.back()->children.push_back(factor());
node->children.back()->name = op.lexeme;
}
return node;
}
int main() {
next_token();
Node* root = program();
if (root != nullptr && error_msg.empty()) {
cout << "Syntax analysis succeeded" << endl;
// TODO: 生成目标代码
}
else {
cout << error_msg << endl;
}
return 0;
}
```
需要注意的是,这个程序只是一个基本的框架,还需要根据具体的编程语言规范进行修改和完善。此外,在实际的编译器中,还需要实现符号表、错误恢复、中间代码生成等功能。
阅读全文