⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.cpp

📁 SSD6 练习4的原版正确答案
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            char op[8];
            strcpy(op, token->str);
            // we can insist on another token because relop must
            // be followed by an expression:
            if (!parse_token()) return false;
            // special treatment for "not in" which is two tokens:
            if (streql(op, "not") && streql(token->str, "in")) {
                strcat(op, token->str); // to make notin
            // special treatment for "is not" which is two tokens:
            } else if (streql(op, "is") && streql(token->str, "not")) {
                strcat(op, token->str); // to make isnot
            } else unget_token();
            return parse_sum() && semantics.relop(op);
        } else return true;
    }
    return false;
}


bool Compiler::parse_sum()
{
    if (parse_prod_expr()) {
        return parse_addends();
    }
    return false;
}


bool Compiler::parse_prod_expr()
{
    if (parse_factor_expr()) {
        return parse_factors();
    }
    return false;
}


bool Compiler::parse_factor_expr()
{
    if (get_token()) {
        if (streql(token->str, "-")) { // unary minus
            return parse_factor_expr() && semantics.unary_minus();
        } else if (streql(token->str, "+")) { // unary plus
            return parse_factor_expr();
        } else if (streql(token->str, "not")) { // not
            return parse_factor_expr() && semantics.not();
        } else if (streql(token->str, "~")) { // logical not
            return parse_factor_expr() && semantics.lognot();
        } else {
            unget_token();
            return parse_exp_expr();
        }
    }
    return false;
}


bool Compiler::parse_exp_expr()
{
    if (parse_inner_expr()) {
        return parse_exponents();
    }
    return false;
}




// parse_inner_expr -- parses an inner_expr or an lval_expr
//
bool Compiler::parse_inner_expr()
{
    if (get_token()) {
		if (streql(token->str, "(")) {
			if (parse_expr()) {
				if (parse_close_paren()) {
					return parse_post_inner(NULL);
				}
			}
		} else if (token->typ == TOKEN_ID) {
			char id[STRING_MAX];
			strcpy(id, token->str);
			return parse_post_inner(id);
		} else if (token->typ == TOKEN_LONG) {
			semantics.push_long(string_to_int(token->str));
			return true;
		} else if (token->typ == TOKEN_DOUBLE) {
			semantics.push_double(atof(token->str));
			return true;
        } else if (token->typ == TOKEN_SYMBOL) {
            semantics.push_symbol(token->str + 1);
            return true;
		} else if (streql(token->str, "[")) {
            // it is possible to apply built-in methods to literal array
			return parse_literal_array() && parse_post_inner(NULL);
        } else if (streql(token->str, "{")) {
            return parse_literal_dict() && parse_post_inner(NULL);
		} else if (token->typ == TOKEN_STRING) {
			semantics.push_string(token->str + 1);
			return true;
		}
	}
    return false;
}


bool Compiler::parse_literal_array()
{
	bool first = true;
	semantics.array_start();
	while (true) {
        if (!parse_token()) return false;
		if (streql(token->str, "]")) {
			return semantics.array_end();
		}
        unget_token();
		if (!first && !parse_comma()) return false;
        if (semantics.before_array_expr() && 
            parse_expr() && 
            semantics.array_expr()) {
		} else return false;
        first = false;
	}
	return false;
}

bool Compiler::parse_literal_dict()
{
	bool first = true;
	semantics.dict_start();
	while (true) {
        if (!parse_token()) return false;
		if (streql(token->str, "}")) {
			return semantics.dict_end();
		}
        unget_token();
		if (!first && !parse_comma()) return false;
        if (!(semantics.before_dict_key() && 
              parse_expr() && 
              semantics.dict_key())) {
            return false;
        }
        if (!parse_colon()) return false;
        if (!(semantics.before_dict_val() && 
              parse_expr() && 
              semantics.dict_val())) {
            return false;
        }
        first = false;
	}
	return false;
}



// parse_post_inner -- parses things that can come after an inner_expr
//
// code generation:
//    if we find an id, call semantics.id(id)
//    if we find id(...), call semantics.call(id)
//    if we find <expr>.meth(...), call semantics.method_call(meth)
//
bool Compiler::parse_post_inner(char *id)
{
    if (get_token()) {
        if (streql(token->str, ".")) {
			if (id) semantics.id(id);
            if (get_token() && (token->typ == TOKEN_ID)) {
                char member[STRING_MAX];
                strcpy(member, token->str);
                if (get_token() && streql(token->str, "(")) {
                    unget_token();
                    if (semantics.method_call(member) && parse_actuals()) {
                        return parse_post_inner(NULL);
                    }
                } else return semantics.field(member) && parse_post_inner(NULL);
            } else {
                expected_method_or_field_selector();
                return false;
            }
        } else if (streql(token->str, "[")) {
			if (id) semantics.id(id);
            if (parse_expr()) {
                if (get_token() && streql(token->str, "]")) {
                    return semantics.aref() && parse_post_inner(NULL);
                } else {
                    expected_close_bracket();
                    return false;
                }
            }
        } else if (streql(token->str, "(")) {
            unget_token();
			semantics.call(id);
            if (!parse_actuals()) return false;
            return parse_post_inner(NULL);
        } else if (id) {
            unget_token();
			semantics.id(id);
            return true;
        }
    }
	unget_token();
    return true;
}


// parse_id_expr -- when called, id is parsed
//
bool Compiler::parse_id_expr(char *id)
{
    if (parse_id_prod_expr(id)) {
        return parse_addends();
    }
    return false;
}


bool Compiler::parse_id_prod_expr(char *id)
{
    if (parse_id_inner_expr(id)) {
        return parse_factors();
    }
    return false;
}


bool Compiler::parse_id_inner_expr(char *id)
{
    // we've gotten the id, so just look for suffixes
    return parse_post_inner(id);
}


bool Compiler::parse_disjunctions()
{
    if (get_token()) {
        if (streql(token->str, "|") || streql(token->str, "or") ||
            streql(token->str, "^") || streql(token->str, "<<") ||
            streql(token->str, ">>")) {
            char op[4];
            strcpy(op, token->str);
            semantics.begin_or(op);
            if (parse_conj()) {
                return parse_disjunctions() &&
                       semantics.end_or(op);
            }
        } else {
            unget_token();
            return true;
        }
    }
    return true;
}


bool Compiler::parse_conjunctions()
{
    if (get_token()) {
        if (streql(token->str, "&") || streql(token->str, "and")) {
            char op[4];
            strcpy(op, token->str);
            semantics.begin_and(op);
            if (parse_relation()) {
                return parse_conjunctions() &&
                       semantics.end_and(op);
            }
        } else {
            unget_token();
            return true;
        }
    }
    return true;
}


bool Compiler::parse_relop()
{
    if (get_token()) {
        if (streql(token->str, "<") ||
            streql(token->str, "<=") ||
            streql(token->str, "==") ||
            streql(token->str, "!=") ||
            streql(token->str, ">") ||
            streql(token->str, ">=") ||
            streql(token->str, "is") ||
            streql(token->str, "in") ||
            streql(token->str, "not")) {
            return true;
        } else {
            unget_token();
            return false;
        }
    }
    return false;
}


bool Compiler::parse_addends()
{
    while (get_token()) {
        if (streql(token->str, "+") || streql(token->str, "-")) {
            char op[4];
            strcpy(op, token->str);
            if (parse_prod_expr()) {
                semantics.addop(op);
            } else return false;
        } else {
            unget_token();
            return true;
        }
    }
    return true;
}


bool Compiler::parse_factors()
{
    while (get_token()) {
        if (streql(token->str, "*") || streql(token->str, "/") || streql(token->str, "%")) {
            char op[4];
            strcpy(op, token->str);
            if (parse_factor_expr()) {
                semantics.mulop(op);
            } else return false;
        } else {
            unget_token();
            return true;
        }
    } 
    return true;
}


bool Compiler::parse_exponents()
{
    while (get_token()) {
        if (streql(token->str, "**")) {
            if (parse_inner_expr()) {
                semantics.power();
            } else return false;
        } else {
            unget_token();
            return true;
        }
    } 
    return true;
}



bool Compiler::parse_actuals()
{
    if (!parse_open_paren()) return false;
	bool first = true;
    bool keyword = false;
    long key_index;
    while (true) {
        if (!parse_token()) return false;
        if (streql(token->str, ")")) {
			return semantics.actual_end();
		}
		unget_token();
        if (!first && !parse_comma()) return false;
        if (!parse_token()) return false;
        if (token->typ == TOKEN_ID) {
            if (!parse_token()) return false;
            if (streql(token->str, "=")) { // keyword parameter
                keyword = true;
                unget_token(); // back up to keyword
                key_index = semantics.insert_symbol(token->str);
                get_token(); // re-get the '='
            } else {
                unget_token();
                unget_token();
            }
        } else {
            unget_token();
        }
        if (!parse_expr()) return false;
		first = false;
		if (keyword) semantics.keyword(key_index);
        else semantics.actual();
        keyword = false;
    }
}


// parse_paren_expr -- parse an expr in parens
//
bool Compiler::parse_paren_expr()
{
    return parse_open_paren() && parse_expr() && parse_close_paren();
}


// parse_class -- assume CLASS already parsed
//
bool Compiler::parse_class()
{
    char cl[STRING_MAX];    // the class name
    char su[STRING_MAX];    // the superclass name

    cl[0] = 0; su[0] = 0;
    if (!parse_id("class name")) return false;
    strcpy(cl, token->str);
    if (!parse_token()) return false;
    if (streql(token->str, "(")) {
        if (!parse_id("super name")) return false;
        strcpy(su, token->str);
        if (!parse_close_paren()) return false;
    } else unget_token();
    if (!parse_colon() || !parse_newline()) return false;
    if (!get_token() || token->typ != TOKEN_INDENT) {
        expected_decl();
        return false;
    }
	if (!semantics.class_start(cl, su)) return false;
    while (true) {
        get_token();
        if (token->typ == TOKEN_DEDENT) return true;
        unget_token();
        if (parse_decl()) {
            // loop to get next declaration
        } else {
            // expected_decl();
            return false;
        }
    }
}
        

bool Compiler::parse_colon()
{
    if (get_token() && streql(token->str, ":")) {
        return true;
    }
    expected_colon();
    return false;
}


bool Compiler::parse_comma()
{
    if (get_token() && streql(token->str, ",")) {
        return true;
    }
    expected_comma();
    return false;
}


bool Compiler::parse_open_paren()
{
    if (get_token() && streql(token->str, "(")) {
        return true;
    }
    expected_open_paren();
    return false;
}


bool Compiler::parse_token()
{
    if (get_token()) return true;
	// get_token returns false on either eof or bad token, e.g. "0x"
	// check for eof and report as error:
	if (!error_flag) expected_token();
    return false;
}

bool Compiler::parse_close_paren()
{
    if (get_token() && streql(token->str, ")")) {
        return true;
    }
    expected_close_paren();
    return false;
}


bool Compiler::parse_var()
{
    while (true) {
        if (get_token()) {
            if (token->typ != TOKEN_ID) break;
			char id[STRING_MAX];
			strcpy(id, token->str);
			semantics.var_decl(id);
            if (get_token()) {
                if (streql(token->str, "=")) {
                    if (!parse_expr()) {
                        return false;
                    }
					semantics.assign_id(id);
                } else unget_token(); // not an equal sign
            }
            if (get_token()) {
                if (token->typ = TOKEN_NEWLINE) {
                    return true;
                } else if (streql(token->str, ",")) {
                    // loop to get next variable
                }
            } else {
                expected_newline();
                return false;
            }
        } else {
            break;
        }
    }
    expected_variable();
    return false;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -