实验二,递归下降语法分析实现

递归下降语法分析实验实现
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef enum {
	TOKEN_ID,
	TOKEN_PLUS,
	TOKEN_STAR,
	TOKEN_LPAREN,
	TOKEN_RPAREN,
	TOKEN_SEMI,
	TOKEN_END,
	TOKEN_ERROR
} TokenType;

typedef struct {
	TokenType type;
	int value; // 仅当type为TOKEN_ID时有效
} Token;

Token* tokenize(const char* input, int* token_count) {
	int size = strlen(input);
	Token* tokens = (Token*)malloc(size * sizeof(Token)); // 添加强制转换
	int pos = 0;
	const char* p = input;
	
	while (*p) {
		if (isspace(*p)) {
			p++;
			continue;
		}
		
		if (isdigit(*p)) {
			int num = 0;
			while (isdigit(*p)) {
				num = num * 10 + (*p - '0');
				p++;
			}
			tokens[pos].type = TOKEN_ID;
			tokens[pos].value = num;
			pos++;
		} else {
			switch (*p) {
			case '+':
				tokens[pos++].type = TOKEN_PLUS;
				break;
			case '*':
				tokens[pos++].type = TOKEN_STAR;
				break;
			case '(':
				tokens[pos++].type = TOKEN_LPAREN;
				break;
			case ')':
				tokens[pos++].type = TOKEN_RPAREN;
				break;
			case ';':
				tokens[pos++].type = TOKEN_SEMI;
				break;
			default:
				fprintf(stderr, "非法字符: %c\n", *p);
				free(tokens);
				return NULL;
			}
			p++;
		}
	}
	
	tokens[pos].type = TOKEN_END;
	*token_count = pos + 1;
	return tokens;
}
Token* tokens;
int pos = 0;
int has_error = 0;

void error(const char* msg) {
	fprintf(stderr, "错误: %s\n", msg);
	has_error = 1;
}

Token peek() {
	return tokens[pos];
}

void consume() {
	pos++;
}

int E();
int E_prime(int val);
int T();
int T_prime(int val);
int F();

// E → T E'
int E() {
	return E_prime(T());
}

// E' → + T E' | ε
int E_prime(int val) {
	if (peek().type == TOKEN_PLUS) {
		consume();
		int t_val = T();
		return E_prime(val + t_val);
	}
	return val;
}

// T → F T'
int T() {
	return T_prime(F());
}

// T' → * F T' | ε
int T_prime(int val) {
	if (peek().type == TOKEN_STAR) {
		consume();
		int f_val = F();
		return T_prime(val * f_val);
	}
	return val;
}

// F → i | ( E )
int F() {
	Token current = peek();
	if (current.type == TOKEN_ID) {
		int value = current.value;
		consume();
		return value;
	} else if (current.type == TOKEN_LPAREN) {
		consume();
		int e_val = E();
		if (peek().type != TOKEN_RPAREN) {
			error("缺少右括号");
			return 0;
		}
		consume();
		return e_val;
	} else {
		error("期望标识符或左括号");
		return 0;
	}
}

int parse_expression() {
	has_error = 0;
	int result = E();
	if (!has_error && peek().type != TOKEN_SEMI) {
		error("缺少分号");
	}
	return has_error ? -1 : result;
}
int main() {
	FILE* fp = fopen("input.txt", "r");
	if (!fp) {
		perror("无法打开文件");
		return 1;
	}
	
	char line[256];
	while (fgets(line, sizeof(line), fp)) {
		line[strcspn(line, "\n")] = 0; // 去除换行符
		
		int token_count;
		Token* tokens = tokenize(line, &token_count);
		if (!tokens) continue;
		
		::tokens = tokens;
		pos = 0;
		int result = parse_expression();
		
		if (has_error) {
			printf("表达式错误: %s\n", line);
		} else {
			printf("结果: %d\n", result);
		}
		
		free(tokens);
	}
	
	fclose(fp);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值