#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;
}
实验二,递归下降语法分析实现

最新推荐文章于 2025-10-14 15:10:42 发布