Skip to content

Commit

Permalink
完成嵌套的if解析,支持if-then/else-fi的流程控制
Browse files Browse the repository at this point in the history
  • Loading branch information
thinszx committed Jan 11, 2021
1 parent f3fdbbe commit 3fad0f0
Show file tree
Hide file tree
Showing 13 changed files with 980 additions and 372 deletions.
164 changes: 89 additions & 75 deletions controlflow.c
Original file line number Diff line number Diff line change
@@ -1,75 +1,89 @@
/*
* controlflow.c - 用来进行流程控制
*/
#include<stdio.h>
#include<string.h>
#include "winshell.h"

enum states {NEUTRAL, WANT_THEN, THEN_BLOCK}; // 将流程控制分为三个分区
enum results {SUCCESS, FAIL};

static int if_state = NEUTRAL;
static int if_result = SUCCESS;
static int processed_stat = 0; // 流程控制语句中进程执行的状态

// 通过当前的if_state判断是否可以进行语句的执行任务
int execute_check() {
int rv = 0; // 检查结果

if (if_state == WANT_THEN) // if后面本应紧跟then却未出现
rv = syn_err((char*)"then expected"); // rv == -1
else if (if_state == THEN_BLOCK && if_result == FAIL) // 未成功执行条件语句
rv = -1;
// 其余情况或中立区,直接执行命令即可,无需判断
return rv;
}

// 判断是否为流程控制语句
int is_control_command(char* s) {
return (strcmp(s, "if") == 0
|| strcmp(s, "then") == 0
|| strcmp(s, "fi") == 0
);
}

// 根据当前if_state的状态进行条件语句的执行
int do_control_command(char** args) {
char* ctrlflag = args[0];
int rv = -1; // 条件语句执行成功标志,默认为不成功

if (strcmp(ctrlflag, "if") == 0) {
if (if_state != NEUTRAL) // 当前不在中立区当中
rv = syn_err((char*)"if unexpected");
else {
processed_stat = process(args + 1); // 指向流程控制语句后的第一部分
if_result = (processed_stat == 0 ? SUCCESS : FAIL);
if_state = WANT_THEN; // 期望then语句,shell中IF后面必须跟then语句
rv = 0; // 返回成功执行标志
}
}
else if (strcmp(ctrlflag, "then") == 0) {
if (if_state != WANT_THEN) // 当前不在WANT_THEN区域中却出现了then
rv = syn_err((char*)"then unexpected");
else {
if_state = THEN_BLOCK;
rv = 0;
}
}
else if (strcmp(ctrlflag, "fi") == 0) {
if (if_state != THEN_BLOCK)
rv = syn_err((char*)"fi unexpected");
else {
if_state = NEUTRAL;
rv = 0;
}
}
else
fatal((char*)"internal error processing: ", ctrlflag, 2);
return rv;
}

int syn_err(char* msg) {
if_state = NEUTRAL;
fprintf_s(stderr, "syntax error: %s\n", msg);
return -1;
}
///*
//* controlflow.c - 用来进行流程控制
//*/
//#include<stdio.h>
//#include<string.h>
//#include "winshell.h"
//
//enum states {NEUTRAL, WANT_THEN, THEN_BLOCK}; // 将流程控制分为三个分区
//enum results {SUCCESS, FAIL};
//
//static int if_state = NEUTRAL;
//static int if_result = SUCCESS;
//static int processed_stat = 0; // 流程控制语句中进程执行的状态
//
//// 通过当前的if_state判断是否可以进行语句的执行任务
//int execute_check() {
// int rv = 0; // 检查结果
//
// if (if_state == WANT_THEN) // if后面本应紧跟then却未出现
// rv = syn_err((char*)"then expected"); // rv == -1
// else if (if_state == THEN_BLOCK && if_result == FAIL) // 未成功执行条件语句
// rv = -1;
// // 其余情况或中立区,直接执行命令即可,无需判断
// return rv;
//}
//
//// 判断是否为流程控制语句
//int is_control_command(char* s) {
// return (strcmp(s, "if") == 0
// || strcmp(s, "then") == 0
// || strcmp(s, "fi") == 0
// );
//}
//
//// 根据当前if_state的状态进行条件语句的执行
//int do_control_command(char** args) {
// char* ctrlflag = args[0];
// int rv = -1; // 条件语句执行成功标志,默认为不成功
//
// if (strcmp(ctrlflag, "if") == 0) {
// if (if_state != NEUTRAL) // 当前不在中立区当中
// rv = syn_err((char*)"if unexpected");
// else {
// processed_stat = process(args + 1); // 指向流程控制语句后的第一部分
// if_result = (processed_stat == 0 ? SUCCESS : FAIL);
// if_state = WANT_THEN; // 期望then语句,shell中IF后面必须跟then语句
// rv = 0; // 返回成功执行标志
// }
// }
// else if (strcmp(ctrlflag, "then") == 0) {
// if (if_state != WANT_THEN) // 当前不在WANT_THEN区域中却出现了then
// rv = syn_err((char*)"then unexpected");
// else {
// if_state = THEN_BLOCK;
// rv = 0;
// }
// }
// else if (strcmp(ctrlflag, "fi") == 0) {
// if (if_state != THEN_BLOCK)
// rv = syn_err((char*)"fi unexpected");
// else {
// if_state = NEUTRAL;
// rv = 0;
// }
// }
// else
// fatal((char*)"internal error processing: ", ctrlflag, 2);
// return rv;
//}
//
//int syn_err(char* msg) {
// if_state = NEUTRAL;
// fprintf_s(stderr, "syntax error: %s\n", msg);
// return -1;
//}
//
//int read_if_block(FILE* fp)
//{
// int ch;
// while ((ch = getc(fp)) != EOF) {
//
// }
// return 0;
//}
//
//int read_loop_block(FILE* fp)
//{
// return 0;
//}
136 changes: 136 additions & 0 deletions controlflow2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include <stdio.h>
#include "winshell2.h"

/*
* if_mode - 用来进行语法上的if、else、then的控制
* laststat - 用来进行逻辑上的判定,通过语法检查+条件的判定,返回是否执行的标志给主程序
*/
static int if_mode = NO_IF; // 初始的if状态
static int laststat; // 用来存储上个命令的执行状态

/* 接下来是维护的if状态栈的定义 */
#define maxn 10 // 支持的嵌套最大值
typedef struct {
int if_mode_store;
int laststat_store;
}env; // 环境变量

typedef struct {
int top; // 栈顶的索引
int fi_empty; // 用来判断当前栈是否还有未弹出的fi
env elements[maxn];
}Stack;

Stack stack = { 0, 0 ,NULL }; // 声明栈

int if_check(char *cmd) {
char* cp;

// 当前读取进来的命令为空,抛出文件尾异常
if (cmd == NULL) {
if (stack.fi_empty !=0) // 证明当前还有fi未弹出栈
syn_err((char*)"lack of fi");
if (if_mode != NO_IF)
syn_err((char*)"EOF unexpected");
return DONT_EXEC;
}

// 检测if
if (strncmp(cmd, "if", 2) == 0 && is_blank(cmd[2])) { // 确保指令是'if '的格式,防止if后直接跟指令
if (save_env() != 0) {
syn_err((char*)"to many if levels(more than 10)"); // if嵌套语法错误
return SYN_ERR;
}
if (if_mode != NO_IF) {
set_ifenv(); // 开始进行嵌套if的执行
// return DONT_EXEC;
}
// 开始执行if后面的语句,检查返回结果
for (cp = cmd + 3; is_blank(*cp); cp++); // 将指针移到if后面的首个非空位置

if (!*cp) {
syn_err((char*)"null command for if");
return DONT_EXEC;
}
laststat = process(cp);
if_mode = SAW_IF;
return DONT_EXEC;
}

// 检测then else fi
// TODO: 检测elif
if (strcmp(cmd, "then") == 0) { // then
if (if_mode != SAW_IF)
syn_err((char*)"\'then\' unexpected");
else
if_mode = SAW_THEN;
return DONT_EXEC;
}
if (strcmp(cmd, "else") == 0) { // else
if (if_mode != SAW_THEN)
syn_err((char*)"\'else\' unexpectd");
else
if_mode = SAW_ELSE;
return DONT_EXEC;
}
if (strcmp(cmd, "fi") == 0) { // fi
if (if_mode != SAW_THEN && if_mode != SAW_ELSE)
syn_err((char*)"\'fi\' unexpected");
else
restore_env();
// 当前fi全部清除完后,无论如何都该将if_mode设为初值
/*if (stack.fi_empty == 0)
if_mode = NO_IF;*/
return DONT_EXEC;
}

// 当前在if块当中
if (if_mode == SAW_IF) {
laststat = process(cmd);
return DONT_EXEC;
}

// 当前并非流程控制语句,开始根据状态执行代码
if (if_mode == NO_IF
|| if_mode == SAW_THEN && laststat == 0
|| if_mode == SAW_ELSE && laststat != 0
)
return OK_EXEC;

return DONT_EXEC;
}

int syn_err(char* msg) {
if_mode = NO_IF;
fprintf_s(stderr, "syntax error: %s\n", msg);
return -1;
}

// 保护当前的if环境,即当前的if_mode和laststat的值
// 实质上等同于压栈操作
int save_env() {
if (stack.top == maxn - 1)
// fatal("If syntax error:", "To many if levels(more than 10)", 2); // if嵌套层数过多
return -1; // if嵌套层数过多
stack.elements[stack.top].if_mode_store = if_mode;
stack.elements[stack.top].laststat_store = laststat;
stack.top++;
stack.fi_empty++;
return 0;
}

// 恢复原有的if环境
// 实质上等同于出栈操作
int restore_env() {
if (stack.top == 0)
return -1; // fi和原来的数量不匹配,比原来的要多
if_mode = stack.elements[--stack.top].if_mode_store;
laststat = stack.elements[stack.top].laststat_store;
stack.fi_empty--;
return 0;
}

void set_ifenv() {
if_mode = SAW_IF;
laststat = 0;
}
Loading

0 comments on commit 3fad0f0

Please sign in to comment.