📄 compiler.cpp
字号:
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 + -