diff options
author | Oxore <oxore@protonmail.com> | 2023-08-07 00:15:22 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-08-07 00:15:22 +0300 |
commit | e73d751459a5777809a18ec322e3e7f6db59ce9d (patch) | |
tree | 1072cfc2e3afd4092f541a8fc034d2296186bf99 | |
parent | 85139bd2345bd8b76cb1725ad08eea4a27fabb13 (diff) |
Extract function to parse sub arg inside parens
-rw-r--r-- | main.c | 158 | ||||
-rwxr-xr-x | test.sh | 1 | ||||
-rw-r--r-- | tests/test1.S | 40 | ||||
-rw-r--r-- | tests/test2.S | 44 |
4 files changed, 133 insertions, 110 deletions
@@ -2152,6 +2152,65 @@ static int pars_parse_arg_starts_with_minus( return pars_parse_arg_after_prefix_expr(self, arg); } +struct inside_parens_state { + bool an1_found, an2_found, dn_found, pc_found; + uint8_t an1, an2, dn, parts; +}; + +static int pars_parse_arg_inside_parens_single_item( + struct pars *const self, + struct arg *const arg, + struct inside_parens_state *const state) +{ + const struct token token0 = pars_peek(self); + if (token0.type == TT_ID) { + // It it may be An/Dn/PC register + struct token_recognition r = pars_recognize_token(self, token0); + if (r.type == RTT_REG) { + // This is definitely a register or regmask. + switch (r.reg) { + case REG_DN: + state->dn_found = true; + state->dn = r.reg_num; + break; + case REG_AN: + if (!state->an1_found) { + state->an1_found = true; + state->an1 = r.reg_num; + } else if (!state->an2_found) { + state->an2_found = true; + state->an2 = r.reg_num; + } else { + return pars_yield_error(self, pars_commit(self), E_EA_PART_NOT_AN); + } + break; + case REG_PC: + state->pc_found = true; + break; + case REG_NONE: + UNREACHABLE(); + case REG_SR: + case REG_CCR: + case REG_USP: + return pars_yield_error(self, pars_commit(self), E_EA_PART); + } + pars_commit(self); + } + } else if (arg->expr.first_token == 0) { + const int ret = pars_parse_expr(self, &arg->expr); + if (ret != OK) { + return ret; + } + } else { + return pars_yield_error(self, self->cur_tok_id, E_EA_PART_NOT_EXPR); + } + state->parts++; + if (pars_is_eof_reached(self)) { + return pars_yield_error_eof(self, E_EA_PART_DELIM); + } + return OK; +} + static int pars_parse_arg_inside_parens( struct pars *const self, struct arg *const arg) { @@ -2160,75 +2219,34 @@ static int pars_parse_arg_inside_parens( // It can be // - (expr)(An) // - (expr)(An,Xi) or (expr)(Xi,An) + // - (expr)(An,Xi.w) or (expr)(Xi.w,An) // - (expr)(PC,Xi) or (expr)(Xi,PC) + // - (expr)(PC,Xi.w) or (expr)(Xi.w,PC) // - (An) or (An)+ // - (An,expr) or (expr,An) // - (PC,expr) or (expr,PC) - // - (An,expr,Xi), (An,Xi,expr), (expr,An,Xi), (expr,Xi,An), (Xi,expr,An) or - // (Xi,An,expr) - // - (PC,expr,Xi), (PC,Xi,expr), (expr,PC,Xi), (expr,Xi,PC), (Xi,expr,PC) or - // (Xi,PC,expr) - bool an1_found = false, an2_found = false, dn_found = false; - bool pc_found = false; - uint8_t an1 = 0, an2 = 0, dn = 0; - unsigned parts = arg->expr.first_token ? 1 : 0; - while (parts < 3) { + // - (An,expr,Xi) in any order (6 variants) + // - (An,expr,Xi.w) in any order (6 variants) + // - (PC,expr,Xi) in any order (6 variants) + // - (PC,expr,Xi.w) in any order (6 variants) + struct inside_parens_state state = { + .parts = arg->expr.first_token ? 1 : 0, + }; + while (state.parts < 3) { if (pars_is_eof_reached(self)) { return pars_yield_error_eof(self, E_EA_PART); } - const struct token token0 = pars_peek(self); - if (token0.type == TT_ID) { - // It it may be An/Dn/PC register - struct token_recognition r = pars_recognize_token(self, token0); - if (r.type == RTT_REG) { - // This is definitely a register or regmask. - switch (r.reg) { - case REG_DN: - dn_found = true; - dn = r.reg_num; - break; - case REG_AN: - if (!an1_found) { - an1_found = true; - an1 = r.reg_num; - } else if (!an2_found) { - an2_found = true; - an2 = r.reg_num; - } else { - return pars_yield_error(self, pars_commit(self), E_EA_PART_NOT_AN); - } - break; - case REG_PC: - pc_found = true; - break; - case REG_NONE: - UNREACHABLE(); - case REG_SR: - case REG_CCR: - case REG_USP: - return pars_yield_error(self, pars_commit(self), E_EA_PART); - } - pars_commit(self); - } - } else if (arg->expr.first_token == 0) { - const int ret = pars_parse_expr(self, &arg->expr); - if (ret != OK) { - return ret; - } - } else { - return pars_yield_error(self, self->cur_tok_id, E_EA_PART_NOT_EXPR); - } - parts++; - if (pars_is_eof_reached(self)) { - return pars_yield_error_eof(self, E_EA_PART_DELIM); + const int ret = pars_parse_arg_inside_parens_single_item(self, arg, &state); + if (ret != OK) { + return ret; } const struct token delim = pars_peek(self); const size_t delim_id = pars_commit(self); if (delim.type == TT_COMMA) { continue; } else if (delim.type == TT_RPAREN) { - if (parts == 1 && arg->expr.first_token) { - assert(!an1_found && !an2_found && !dn_found && !pc_found); + if (state.parts == 1 && arg->expr.first_token) { + assert(!state.an1_found && !state.an2_found && !state.dn_found && !state.pc_found); // It turns out we are inside of expression, so this closing // parenthesis is part of it. Let's accumulate it and move // on. @@ -2242,9 +2260,9 @@ static int pars_parse_arg_inside_parens( return pars_yield_error(self, delim_id, E_EA_PART); } } - if (parts == 1 && an1_found) { + if (state.parts == 1 && state.an1_found) { // It is either (An) or (An)+ - assert(!pc_found && !dn_found && !arg->expr.first_token); + assert(!state.pc_found && !state.dn_found && !arg->expr.first_token); if (pars_is_eof_reached(self)) { arg->type = ARG_AN_ADDR; } else { @@ -2256,34 +2274,34 @@ static int pars_parse_arg_inside_parens( arg->type = ARG_AN_ADDR; } } - arg->xn = an1; + arg->xn = state.an1; arg->num_tokens = self->cur_tok_id - arg->first_token; return OK; - } else if (parts == 2 && an1_found && arg->expr.first_token) { + } else if (state.parts == 2 && state.an1_found && arg->expr.first_token) { // It is (An,d16) or (d16,An) - assert(!an2_found && !pc_found && !dn_found); + assert(!state.an2_found && !state.pc_found && !state.dn_found); arg->type = ARG_AN_ADDR_16; - arg->xn = an1; + arg->xn = state.an1; arg->num_tokens = self->cur_tok_id - arg->first_token; return OK; - } else if (parts == 2 && pc_found && arg->expr.first_token) { + } else if (state.parts == 2 && state.pc_found && arg->expr.first_token) { // It is (PC,d16) or (d16,PC) - assert(!an1_found && !an2_found && !dn_found); + assert(!state.an1_found && !state.an2_found && !state.dn_found); arg->type = ARG_PC_ADDR_16; arg->num_tokens = self->cur_tok_id - arg->first_token; return OK; - } else if (parts == 3 && pc_found && arg->expr.first_token && (an1_found || dn_found)) { + } else if (state.parts == 3 && state.pc_found && arg->expr.first_token && (state.an1_found || state.dn_found)) { // It is (d8,PC,Xn) - assert((an1_found && !dn_found) || (!an1_found && dn_found)); + assert((state.an1_found && !state.dn_found) || (!state.an1_found && state.dn_found)); arg->type = ARG_PC_ADDR_8_XI; - arg->xi = an1_found ? (an1 | 0x8) : dn; + arg->xi = state.an1_found ? (state.an1 | 0x8) : state.dn; arg->num_tokens = self->cur_tok_id - arg->first_token; return OK; - } else if (parts == 3 && an1_found && arg->expr.first_token && (an2_found || dn_found)) { + } else if (state.parts == 3 && state.an1_found && arg->expr.first_token && (state.an2_found || state.dn_found)) { // It is (d8,An,Xn) - assert((an2_found && !dn_found) || (!an2_found && dn_found)); + assert((state.an2_found && !state.dn_found) || (!state.an2_found && state.dn_found)); arg->type = ARG_AN_ADDR_8_XI; - arg->xi = an2_found ? (an2 | 0x8) : dn; + arg->xi = state.an2_found ? (state.an2 | 0x8) : state.dn; arg->num_tokens = self->cur_tok_id - arg->first_token; return OK; } @@ -11,4 +11,5 @@ set INCLUDE68=e:\\sierra\\include set TEMP=c:\\tmp END echo "asm68 -l -Q -o test1.o test1.S" >>"$dosbuild_dir/build.bat" +echo "asm68 -l -Q -o test2.o test2.S" >>"$dosbuild_dir/build.bat" dosemu -quiet -K "$dosbuild_dir" -E'build.bat' diff --git a/tests/test1.S b/tests/test1.S index 5b79cec..07d1ce1 100644 --- a/tests/test1.S +++ b/tests/test1.S @@ -13,61 +13,21 @@ move (32767,pc),d1 move (pc,32767),d1 move 127(a1,d1),d1 -move 127(a1,d1.l),d1 -move 127(a1,d1.l),d1 -move 127.l(a1,d1.l),d1 move 127(d1,a1),d1 -move 127(d1.l,a1),d1 -move 127(d1.l,a1),d1 -move 127.l(d1.l,a1),d1 move 127(pc,d1),d1 -move 127(pc,d1.l),d1 -move 127.l(pc,d1),d1 -move 127.l(pc,d1.l),d1 move 127(d1,pc),d1 -move 127(d1.l,pc),d1 -move 127.l(d1,pc),d1 -move 127.l(d1.l,pc),d1 move (a1,d1,127),d1 -move (a1,d1.l,127),d1 -move (a1,d1.l,127.l),d1 -move (a1,d1,127.l),d1 move (d1,a1,127),d1 -move (d1.l,a1,127),d1 -move (d1,a1,127.l),d1 -move (d1.l,a1,127.l),d1 move (a1,127,d1),d1 -move (a1,127,d1.l),d1 -move (a1,127.l,d1),d1 -move (a1,127.l,d1.l),d1 move (d1,127,a1),d1 -move (d1.l,127,a1),d1 -move (d1,127.l,a1),d1 -move (d1.l,127.l,a1),d1 -move (d1.l,127.l,a1),d1 -move (a1.l,127.l,a1),d1 move (pc,d1,127),d1 -move (pc,d1.l,127),d1 -move (pc,d1,127.l),d1 move (d1,pc,127),d1 -move (d1.l,pc,127),d1 -move (d1,pc,127.l),d1 -move (d1.l,pc,127.l),d1 move (pc,127,d1),d1 -move (pc,127,d1.l),d1 -move (pc,127.l,d1),d1 -move (pc,127.l,d1.l),d1 move (d1,127,pc),d1 -move (d1.l,127,pc),d1 -move (d1,127.l,pc),d1 -move (d1.l,127.l,pc),d1 -loc: -move 0.l,d1 -move loc.l,d1 move #127,d1 move #-128,d1 move #255,d1 diff --git a/tests/test2.S b/tests/test2.S new file mode 100644 index 0000000..4a8ee7d --- /dev/null +++ b/tests/test2.S @@ -0,0 +1,44 @@ +move 127(a1,d1.l),d1 +move 127(a1,d1.l),d1 +move 127.l(a1,d1.l),d1 +move 127(d1.l,a1),d1 +move 127(d1.l,a1),d1 +move 127.l(d1.l,a1),d1 + +move 127(pc,d1.l),d1 +move 127.l(pc,d1),d1 +move 127.l(pc,d1.l),d1 +move 127(d1.l,pc),d1 +move 127.l(d1,pc),d1 +move 127.l(d1.l,pc),d1 + +move (a1,d1.l,127),d1 +move (a1,d1.l,127.l),d1 +move (a1,d1,127.l),d1 +move (d1.l,a1,127),d1 +move (d1,a1,127.l),d1 +move (d1.l,a1,127.l),d1 +move (a1,127,d1.l),d1 +move (a1,127.l,d1),d1 +move (a1,127.l,d1.l),d1 +move (d1.l,127,a1),d1 +move (d1,127.l,a1),d1 +move (d1.l,127.l,a1),d1 +move (d1.l,127.l,a1),d1 +move (a1.l,127.l,a1),d1 + +move (pc,d1.l,127),d1 +move (pc,d1,127.l),d1 +move (d1.l,pc,127),d1 +move (d1,pc,127.l),d1 +move (d1.l,pc,127.l),d1 +move (pc,127,d1.l),d1 +move (pc,127.l,d1),d1 +move (pc,127.l,d1.l),d1 +move (d1.l,127,pc),d1 +move (d1,127.l,pc),d1 +move (d1.l,127.l,pc),d1 + +loc: +move 0.l,d1 +move loc.l,d1 |