// Get a statement numvar getstatement(void) { numvar retval = 0; #if !defined(TINY_BUILD) && !defined(UNIX_BUILD) chkbreak(); #endif if (sym == s_while) { // at this point sym is pointing at s_while, before the conditional expression // save fetchptr so we can restart parsing from here as the while iterates parsepoint fetchmark; markparsepoint(&fetchmark); for (;;) { returntoparsepoint(&fetchmark, 0); getsym(); // fetch the start of the conditional if (getnum()) { retval = getstatement(); if (sym == s_returning) break; // exit if we caught a return } else { skipstatement(); break; } } } else if (sym == s_if) { getsym(); // eat "if" if (getnum()) { retval = getstatement(); if (sym == s_else) { getsym(); // eat "else" skipstatement(); } } else { skipstatement(); if (sym == s_else) { getsym(); // eat "else" retval = getstatement(); } } } else if (sym == s_lcurly) { getsym(); // eat "{" while ((sym != s_eof) && (sym != s_returning) && (sym != s_rcurly)) retval = getstatement(); if (sym == s_rcurly) getsym(); // eat "}" } else if (sym == s_return) { getsym(); // eat "return" if ((sym != s_eof) && (sym != s_semi)) retval = getnum(); sym = s_returning; // signal we're returning up the line } #if !defined(TINY_BUILD) else if (sym == s_switch) retval = getswitchstatement(); #endif else if (sym == s_function) cmd_function(); else if (sym == s_run) { // run macroname getsym(); if ((sym != s_script_eeprom) && (sym != s_script_progmem) && (sym != s_script_file)) unexpected(M_id); // address of macroid is in symval via parseid // check for [,snoozeintervalms] getsym(); // eat macroid to check for comma; symval untouched if (sym == s_comma) { vpush(symval); getsym(); // eat the comma getnum(); // get a number or else startTask(vpop(), expval); } else startTask(symval, 0); } else if (sym == s_stop) { getsym(); #if !defined(TINY_BUILD) if (sym == s_mul) { // stop * stops all tasks initTaskList(); getsym(); } else if ((sym == s_semi) || (sym == s_eof)) { if (background) stopTask(curtask); // stop with no args stops the current task IF we're in back else initTaskList(); // in foreground, stop all } else #endif stopTask(getnum()); } else if (sym == s_rm) { // rm "sym" or rm * getsym(); if (sym == s_script_eeprom) { eraseentry(idbuf); } #if !defined(TINY_BUILD) else if (sym == s_mul) nukeeeprom(); #endif else if (sym != s_undef) expected(M_id); getsym(); } else if (sym == s_ls) { getsym(); cmd_ls(); } #if !defined(TINY_BUILD) else if (sym == s_boot) cmd_boot(); else if (sym == s_ps) { getsym(); showTaskList(); } else if (sym == s_peep) { getsym(); cmd_peep(); } else if (sym == s_help) { getsym(); cmd_help(); } #endif else if (sym == s_print) { getsym(); cmd_print(); } else if (sym == s_semi) { ; } // ;) #ifdef HEX_UPLOAD // a line beginning with a colon is treated as a hex record // containing data to upload to eeprom // // TODO: verify checksum // else if (sym == s_colon) { // fetchptr points at the byte count byte byteCount = gethex(2); // 2 bytes byte count int addr = gethex(4); // 4 bytes address byte recordType = gethex(2); // 2 bytes record type; now fetchptr -> data if (recordType == 1) reboot(); // reboot on EOF record (01) if (recordType != 0) return; // we only handle the data record (00) if (addr == 0) nukeeeprom(); // auto-clear eeprom on write to 0000 while (byteCount--) eewrite(addr++, gethex(2)); // update the eeprom gethex(2); // discard the checksum getsym(); // and re-prime the parser } #endif else { getexpression(); retval = expval; } if (sym == s_semi) getsym(); // eat trailing ';' return retval; }
// Parse and execute a list of statements separated by semicolons // // numvar getstatementlist(void) { numvar retval = 0; while ((sym != s_eof) && (sym != s_returning)) retval = getstatement(); return retval; }