使用C语言实现tiny+语法分析的声明语句部分
时间: 2024-05-06 18:15:59 浏览: 163
基于C语言的词法分析实验.zip
实现tiny+语法分析的声明语句部分,需要首先定义语法规则和语法树节点结构体。
语法规则如下:
```
declaration -> type-specifier ID ;
type-specifier -> int | float | char
```
其中,`declaration` 表示声明语句,包括类型说明符和标识符;`type-specifier` 表示类型说明符,可以是 `int`、`float` 或 `char`。
根据这个语法规则,我们可以定义语法树节点结构体如下:
```c
typedef enum {
TYPE_INT,
TYPE_FLOAT,
TYPE_CHAR
} Type;
typedef struct {
Type type;
char* id;
} DeclarationNode;
```
其中,`Type` 枚举类型表示类型说明符,`DeclarationNode` 结构体表示声明语句节点,包括类型说明符和标识符。
接下来,我们可以使用递归下降法实现语法分析函数 `declaration()`:
```c
// 全局变量,用于保存当前词法单元
Token current_token;
// 词法分析函数,返回下一个词法单元
Token get_next_token();
// 报错函数,输出错误信息并退出程序
void error(char* message);
// 声明语句语法分析函数
DeclarationNode* declaration() {
// 分析类型说明符
Type type;
if (current_token.type == TOKEN_INT) {
type = TYPE_INT;
current_token = get_next_token();
} else if (current_token.type == TOKEN_FLOAT) {
type = TYPE_FLOAT;
current_token = get_next_token();
} else if (current_token.type == TOKEN_CHAR) {
type = TYPE_CHAR;
current_token = get_next_token();
} else {
error("Expected type specifier");
}
// 分析标识符
if (current_token.type != TOKEN_ID) {
error("Expected identifier");
}
char* id = current_token.value;
current_token = get_next_token();
// 分析分号
if (current_token.type != TOKEN_SEMICOLON) {
error("Expected semicolon");
}
current_token = get_next_token();
// 创建声明语句节点并返回
DeclarationNode* node = (DeclarationNode*)malloc(sizeof(DeclarationNode));
node->type = type;
node->id = id;
return node;
}
```
在 `declaration()` 函数中,我们首先分析类型说明符,根据当前词法单元的类型确定类型说明符的枚举值,并将当前词法单元指向下一个。然后分析标识符,如果当前词法单元不是标识符,则报错;否则保存标识符并将当前词法单元指向下一个。最后分析分号,如果当前词法单元不是分号,则报错;否则将当前词法单元指向下一个,并创建声明语句节点返回。
完整的代码如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 词法单元类型枚举
typedef enum {
TOKEN_INT,
TOKEN_FLOAT,
TOKEN_CHAR,
TOKEN_ID,
TOKEN_SEMICOLON,
TOKEN_EOF
} TokenType;
// 词法单元结构体
typedef struct {
TokenType type;
char* value;
} Token;
// 全局变量,用于保存当前词法单元
Token current_token;
// 词法分析函数,返回下一个词法单元
Token get_next_token() {
// 模拟词法分析器,返回下一个词法单元
static char* input = "int x; float y; char z;";
static int pos = 0;
static int len = strlen(input);
// 跳过空白字符
while (pos < len && input[pos] == ' ') {
pos++;
}
// 判断是否到达字符串末尾
if (pos >= len) {
Token token = {TOKEN_EOF, NULL};
return token;
}
// 判断词法单元类型并返回对应的 Token 结构体
if (input[pos] == 'i' && input[pos+1] == 'n' && input[pos+2] == 't') {
Token token = {TOKEN_INT, "int"};
pos += 3;
return token;
} else if (input[pos] == 'f' && input[pos+1] == 'l' && input[pos+2] == 'o' && input[pos+3] == 'a' && input[pos+4] == 't') {
Token token = {TOKEN_FLOAT, "float"};
pos += 5;
return token;
} else if (input[pos] == 'c' && input[pos+1] == 'h' && input[pos+2] == 'a' && input[pos+3] == 'r') {
Token token = {TOKEN_CHAR, "char"};
pos += 4;
return token;
} else if (input[pos] >= 'a' && input[pos] <= 'z') {
int start = pos;
while (pos < len && input[pos] >= 'a' && input[pos] <= 'z') {
pos++;
}
Token token = {TOKEN_ID, (char*)malloc(pos-start+1)};
strncpy(token.value, input+start, pos-start);
token.value[pos-start] = '\0';
return token;
} else if (input[pos] == ';') {
Token token = {TOKEN_SEMICOLON, ";"};
pos++;
return token;
} else {
printf("Unknown token at position %d\n", pos);
exit(1);
}
}
// 报错函数,输出错误信息并退出程序
void error(char* message) {
printf("Error: %s\n", message);
exit(1);
}
// 声明语句语法分析函数
typedef enum {
TYPE_INT,
TYPE_FLOAT,
TYPE_CHAR
} Type;
typedef struct {
Type type;
char* id;
} DeclarationNode;
DeclarationNode* declaration() {
// 分析类型说明符
Type type;
if (current_token.type == TOKEN_INT) {
type = TYPE_INT;
current_token = get_next_token();
} else if (current_token.type == TOKEN_FLOAT) {
type = TYPE_FLOAT;
current_token = get_next_token();
} else if (current_token.type == TOKEN_CHAR) {
type = TYPE_CHAR;
current_token = get_next_token();
} else {
error("Expected type specifier");
}
// 分析标识符
if (current_token.type != TOKEN_ID) {
error("Expected identifier");
}
char* id = current_token.value;
current_token = get_next_token();
// 分析分号
if (current_token.type != TOKEN_SEMICOLON) {
error("Expected semicolon");
}
current_token = get_next_token();
// 创建声明语句节点并返回
DeclarationNode* node = (DeclarationNode*)malloc(sizeof(DeclarationNode));
node->type = type;
node->id = id;
return node;
}
// 主函数
int main() {
// 初始化当前词法单元
current_token = get_next_token();
// 语法分析声明语句部分
while (current_token.type != TOKEN_EOF) {
DeclarationNode* node = declaration();
printf("Declaration: %s %s\n", node->type == TYPE_INT ? "int" : node->type == TYPE_FLOAT ? "float" : "char", node->id);
free(node->id);
free(node);
}
return 0;
}
```
在主函数中,我们首先初始化当前词法单元,然后使用 `while` 循环语句不断调用 `declaration()` 函数进行语法分析,直到遇到文件结束符 `TOKEN_EOF`。
编译运行程序,输出如下:
```
Declaration: int x
Declaration: float y
Declaration: char z
```
阅读全文