clean up some more parser routines

master
Daniel Kolesa 2021-04-10 07:32:44 +02:00
parent a6426c60ee
commit 51f09c3dfb
2 changed files with 108 additions and 110 deletions

View File

@ -927,36 +927,36 @@ bool parser_state::parse_arg(int ltype, charbuf *word) {
} }
} }
static void compile_cmd( bool parser_state::parse_call_command(
parser_state &gs, command_impl *id, ident &self, bool &more, int rettype, command_impl *id, ident &self, int rettype, std::uint32_t limit
std::uint32_t limit = 0
) { ) {
std::uint32_t comtype = BC_INST_COM, numargs = 0, numcargs = 0, fakeargs = 0; std::uint32_t comtype = BC_INST_COM, numargs = 0, numcargs = 0, fakeargs = 0;
bool rep = false; bool rep = false;
auto fmt = id->get_args(); auto fmt = id->get_args();
bool more = true;
for (auto it = fmt.begin(); it != fmt.end(); ++it) { for (auto it = fmt.begin(); it != fmt.end(); ++it) {
switch (*it) { switch (*it) {
case 's': /* string */ case 's': /* string */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_STRING); more = parse_arg(VAL_STRING);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_string(); gs.gen_val_string();
fakeargs++; fakeargs++;
} else if ((it + 1) == fmt.end()) { } else if ((it + 1) == fmt.end()) {
int numconc = 1; int numconc = 1;
for (;;) { for (;;) {
more = gs.parse_arg(VAL_STRING); more = parse_arg(VAL_STRING);
if (!more) { if (!more) {
break; break;
} }
numconc++; numconc++;
} }
if (numconc > 1) { if (numconc > 1) {
gs.gs.gen_concat(numconc, true, VAL_STRING); gs.gen_concat(numconc, true, VAL_STRING);
} }
} }
numargs++; numargs++;
@ -964,13 +964,13 @@ static void compile_cmd(
break; break;
case 'i': /* integer */ case 'i': /* integer */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_INT); more = parse_arg(VAL_INT);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_integer(); gs.gen_val_integer();
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -978,13 +978,13 @@ static void compile_cmd(
break; break;
case 'b': /* integer, INT_MIN default */ case 'b': /* integer, INT_MIN default */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_INT); more = parse_arg(VAL_INT);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_integer(std::numeric_limits<integer_type>::min()); gs.gen_val_integer(std::numeric_limits<integer_type>::min());
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -992,13 +992,13 @@ static void compile_cmd(
break; break;
case 'f': /* float */ case 'f': /* float */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_FLOAT); more = parse_arg(VAL_FLOAT);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_float(); gs.gen_val_float();
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -1006,13 +1006,13 @@ static void compile_cmd(
break; break;
case 'F': /* float, prev-argument default */ case 'F': /* float, prev-argument default */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_FLOAT); more = parse_arg(VAL_FLOAT);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_dup(VAL_FLOAT); gs.gen_dup(VAL_FLOAT);
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -1020,13 +1020,13 @@ static void compile_cmd(
break; break;
case 't': /* any arg */ case 't': /* any arg */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_ANY); more = parse_arg(VAL_ANY);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_null(); gs.gen_val_null();
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -1034,13 +1034,13 @@ static void compile_cmd(
break; break;
case 'E': /* condition */ case 'E': /* condition */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_COND); more = parse_arg(VAL_COND);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_null(); gs.gen_val_null();
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -1048,13 +1048,13 @@ static void compile_cmd(
break; break;
case 'e': /* code */ case 'e': /* code */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_CODE); more = parse_arg(VAL_CODE);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_block(); gs.gen_block();
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -1062,31 +1062,31 @@ static void compile_cmd(
break; break;
case 'r': /* ident */ case 'r': /* ident */
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
more = gs.parse_arg(VAL_IDENT); more = parse_arg(VAL_IDENT);
} }
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
if (rep) { if (rep) {
break; break;
} }
gs.gs.gen_val_ident(); gs.gen_val_ident();
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
numcargs++; numcargs++;
break; break;
case '$': /* self */ case '$': /* self */
gs.gs.gen_val_ident(self); gs.gen_val_ident(self);
numargs++; numargs++;
break; break;
case 'N': /* number of arguments */ case 'N': /* number of arguments */
gs.gs.gen_val_integer(numargs - fakeargs); gs.gen_val_integer(numargs - fakeargs);
numargs++; numargs++;
break; break;
case 'C': /* concatenated string */ case 'C': /* concatenated string */
comtype = BC_INST_COM_C; comtype = BC_INST_COM_C;
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
for (;;) { for (;;) {
more = gs.parse_arg(VAL_ANY); more = parse_arg(VAL_ANY);
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
break; break;
} }
@ -1099,7 +1099,7 @@ static void compile_cmd(
comtype = BC_INST_COM_V; comtype = BC_INST_COM_V;
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
for(;;) { for(;;) {
more = gs.parse_arg(VAL_ANY); more = parse_arg(VAL_ANY);
if (!more || (limit && (numcargs >= limit))) { if (!more || (limit && (numcargs >= limit))) {
break; break;
} }
@ -1120,124 +1120,118 @@ static void compile_cmd(
break; break;
} }
} }
gs.gs.gen_command_call(*id, comtype, rettype, numargs); gs.gen_command_call(*id, comtype, rettype, numargs);
return more;
} }
static void compile_alias(parser_state &gs, alias *id, bool &more) { bool parser_state::parse_call_alias(alias &id) {
bool more;
std::uint32_t numargs = 0; std::uint32_t numargs = 0;
for (;;) { for (;;) {
more = gs.parse_arg(VAL_ANY); more = parse_arg(VAL_ANY);
if (!more) { if (!more) {
break; break;
} }
++numargs; ++numargs;
} }
gs.gs.gen_alias_call(*id, numargs); gs.gen_alias_call(id, numargs);
return more;
} }
static void compile_local(parser_state &gs, bool &more) { bool parser_state::parse_id_local() {
bool more;
std::uint32_t numargs = 0; std::uint32_t numargs = 0;
if (more) { for (;;) {
for (;;) { more = parse_arg(VAL_IDENT);
more = gs.parse_arg(VAL_IDENT); if (!more) {
if (!more) { break;
break;
}
numargs++;
} }
numargs++;
} }
gs.gs.gen_local(numargs); gs.gen_local(numargs);
return more;
} }
static void compile_do( bool parser_state::parse_id_do(bool args, int ltype) {
parser_state &gs, bool args, int rettype, bool &more bool more = parse_arg(VAL_CODE);
) {
if (more) {
more = gs.parse_arg(VAL_CODE);
}
if (!more) { if (!more) {
gs.gs.gen_result_null(rettype); gs.gen_result_null(ltype);
} else { } else {
gs.gs.gen_do(args, rettype); gs.gen_do(args, ltype);
} }
return more;
} }
static void compile_if( bool parser_state::parse_id_if(ident &id, int ltype) {
parser_state &gs, ident *id, bool &more, int rettype /* condition */
) { bool more = parse_arg(VAL_ANY);
if (more) {
/* condition */
more = gs.parse_arg(VAL_ANY);
}
if (!more) { if (!more) {
/* no condition: expr is nothing */ /* no condition: expr is nothing */
gs.gs.gen_result_null(rettype); gs.gen_result_null(ltype);
} else { } else {
auto tpos = gs.gs.count(); auto tpos = gs.count();
/* true block */ /* true block */
more = gs.parse_arg(VAL_CODE); more = parse_arg(VAL_CODE);
if (!more) { if (!more) {
/* we only had condition: expr is nothing */ /* we only had condition: expr is nothing */
gs.gs.gen_pop(); gs.gen_pop();
gs.gs.gen_result_null(rettype); gs.gen_result_null(ltype);
} else { } else {
auto fpos = gs.gs.count(); auto fpos = gs.count();
/* false block */ /* false block */
more = gs.parse_arg(VAL_CODE); more = parse_arg(VAL_CODE);
if (!gs.gs.gen_if(tpos, more ? fpos : 0)) { if (!gs.gen_if(tpos, more ? fpos : 0)) {
/* can't fully compile: use a call */ /* can't fully compile: use a call */
gs.gs.gen_command_call(*id, BC_INST_COM, rettype); gs.gen_command_call(id, BC_INST_COM, ltype);
} }
} }
} }
return more;
} }
static void compile_and_or( bool parser_state::parse_id_and_or(ident &id, int ltype) {
parser_state &gs, ident *id, bool &more, int rettype
) {
std::uint32_t numargs = 0; std::uint32_t numargs = 0;
if (more) { /* first */
/* first */ bool more = parse_arg(VAL_COND);
more = gs.parse_arg(VAL_COND);
}
if (!more) { if (!more) {
/* no first: generate true or false */ /* no first: generate true or false */
if (ident_p{*id}.impl().p_type == ID_AND) { if (ident_p{id}.impl().p_type == ID_AND) {
gs.gs.gen_result_true(rettype); gs.gen_result_true(ltype);
} else { } else {
gs.gs.gen_result_false(rettype); gs.gen_result_false(ltype);
} }
} else { } else {
numargs++; numargs++;
std::size_t start = gs.gs.count(), end = start; std::size_t start = gs.count(), end = start;
for (;;) { for (;;) {
/* keep going as long as we only get blocks */ /* keep going as long as we only get blocks */
more = gs.parse_arg(VAL_COND); more = parse_arg(VAL_COND);
if (!more) { if (!more) {
break; break;
} }
numargs++; numargs++;
if (!gs.gs.is_block(end)) { if (!gs.is_block(end)) {
break; break;
} }
end = gs.gs.count(); end = gs.count();
} }
if (more) { if (more) {
/* last parsed thing was not a block, fall back to call */ /* last parsed thing was not a block, fall back to call */
for (;;) { for (;;) {
/* but first, parse out the remainder of values */ /* but first, parse out the remainder of values */
more = gs.parse_arg(VAL_COND); more = parse_arg(VAL_COND);
if (!more) { if (!more) {
break; break;
} }
numargs++; numargs++;
} }
gs.gs.gen_command_call(*id, BC_INST_COM_V, rettype, numargs); gs.gen_command_call(id, BC_INST_COM_V, ltype, numargs);
} else { } else {
/* all blocks and nothing left */ /* all blocks and nothing left */
gs.gs.gen_and_or((ident_p{*id}.impl().p_type != ID_AND), start); gs.gen_and_or((ident_p{id}.impl().p_type != ID_AND), start);
} }
} }
return more;
} }
void parser_state::parse_block(int rettype, int brak) { void parser_state::parse_block(int rettype, int brak) {
@ -1280,25 +1274,25 @@ void parser_state::parse_block(int rettype, int brak) {
goto endstatement; goto endstatement;
case ident_type::IVAR: { case ident_type::IVAR: {
auto *hid = ts.istate->cmd_ivar; auto *hid = ts.istate->cmd_ivar;
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(hid), static_cast<command_impl *>(hid),
id, more, rettype, 1 id, rettype, 1
); );
goto endstatement; goto endstatement;
} }
case ident_type::FVAR: { case ident_type::FVAR: {
auto *hid = ts.istate->cmd_fvar; auto *hid = ts.istate->cmd_fvar;
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(hid), static_cast<command_impl *>(hid),
id, more, rettype, 1 id, rettype, 1
); );
goto endstatement; goto endstatement;
} }
case ident_type::SVAR: { case ident_type::SVAR: {
auto *hid = ts.istate->cmd_svar; auto *hid = ts.istate->cmd_svar;
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(hid), static_cast<command_impl *>(hid),
id, more, rettype, 1 id, rettype, 1
); );
goto endstatement; goto endstatement;
} }
@ -1353,27 +1347,24 @@ noid:
} else { } else {
switch (ident_p{*id}.impl().p_type) { switch (ident_p{*id}.impl().p_type) {
case ID_ALIAS: case ID_ALIAS:
compile_alias( more = parse_call_alias(static_cast<alias &>(*id));
*this, static_cast<alias *>(id), more
);
break; break;
case ID_COMMAND: case ID_COMMAND:
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(id), *id, more, static_cast<command_impl *>(id), *id, rettype
rettype
); );
break; break;
case ID_LOCAL: case ID_LOCAL:
compile_local(*this, more); more = parse_id_local();
break; break;
case ID_DO: case ID_DO:
compile_do(*this, false, rettype, more); more = parse_id_do(false, rettype);
break; break;
case ID_DOARGS: case ID_DOARGS:
compile_do(*this, true, rettype, more); more = parse_id_do(true, rettype);
break; break;
case ID_IF: case ID_IF:
compile_if(*this, id, more, rettype); more = parse_id_if(*id, rettype);
break; break;
case ID_BREAK: case ID_BREAK:
gs.gen_break(); gs.gen_break();
@ -1403,29 +1394,26 @@ noid:
break; break;
case ID_AND: case ID_AND:
case ID_OR: case ID_OR:
compile_and_or(*this, id, more, rettype); more = parse_id_and_or(*id, rettype);
break; break;
case ID_IVAR: { case ID_IVAR: {
auto *hid = ts.istate->cmd_ivar; auto *hid = ts.istate->cmd_ivar;
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(hid), static_cast<command_impl *>(hid), *id, rettype
*id, more, rettype
); );
break; break;
} }
case ID_FVAR: { case ID_FVAR: {
auto *hid = ts.istate->cmd_fvar; auto *hid = ts.istate->cmd_fvar;
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(hid), static_cast<command_impl *>(hid), *id, rettype
*id, more, rettype
); );
break; break;
} }
case ID_SVAR: { case ID_SVAR: {
auto *hid = ts.istate->cmd_svar; auto *hid = ts.istate->cmd_svar;
compile_cmd( more = parse_call_command(
*this, static_cast<command_impl *>(hid), static_cast<command_impl *>(hid), *id, rettype
*id, more, rettype
); );
break; break;
} }

View File

@ -72,6 +72,16 @@ struct parser_state {
bool parse_subblock(); bool parse_subblock();
void parse_blockarg(int ltype); void parse_blockarg(int ltype);
bool parse_arg(int ltype, charbuf *word = nullptr); bool parse_arg(int ltype, charbuf *word = nullptr);
bool parse_call_command(
command_impl *id, ident &self, int rettype, std::uint32_t limit = 0
);
bool parse_call_alias(alias &id);
bool parse_id_local();
bool parse_id_do(bool args, int ltype);
bool parse_id_if(ident &id, int ltype);
bool parse_id_and_or(ident &id, int ltype);
}; };
} /* namespace cubescript */ } /* namespace cubescript */