protected virtual object EvalStart(ParseTree tree, params object[] paramlist) { return("Could not interpret input; no semantics implemented."); }
protected object GetValue(ParseTree tree, TokenType type, int index) { return(GetValue(tree, type, ref index)); }
/// <summary> /// this implements the evaluation functionality, cannot be used directly /// </summary> /// <param name="tree">the parsetree itself</param> /// <param name="paramlist">optional input parameters</param> /// <returns>a partial result of the evaluation</returns> internal object Eval(ParseTree tree, params object[] paramlist) { object Value = null; switch (Token.Type) { case TokenType.Start: Value = EvalStart(tree, paramlist); break; case TokenType.instruction_block: Value = Evalinstruction_block(tree, paramlist); break; case TokenType.instruction: Value = Evalinstruction(tree, paramlist); break; case TokenType.lazyglobal_directive: Value = Evallazyglobal_directive(tree, paramlist); break; case TokenType.directive: Value = Evaldirective(tree, paramlist); break; case TokenType.empty_stmt: Value = Evalempty_stmt(tree, paramlist); break; case TokenType.set_stmt: Value = Evalset_stmt(tree, paramlist); break; case TokenType.if_stmt: Value = Evalif_stmt(tree, paramlist); break; case TokenType.until_stmt: Value = Evaluntil_stmt(tree, paramlist); break; case TokenType.fromloop_stmt: Value = Evalfromloop_stmt(tree, paramlist); break; case TokenType.unlock_stmt: Value = Evalunlock_stmt(tree, paramlist); break; case TokenType.print_stmt: Value = Evalprint_stmt(tree, paramlist); break; case TokenType.on_stmt: Value = Evalon_stmt(tree, paramlist); break; case TokenType.toggle_stmt: Value = Evaltoggle_stmt(tree, paramlist); break; case TokenType.wait_stmt: Value = Evalwait_stmt(tree, paramlist); break; case TokenType.when_stmt: Value = Evalwhen_stmt(tree, paramlist); break; case TokenType.onoff_stmt: Value = Evalonoff_stmt(tree, paramlist); break; case TokenType.onoff_trailer: Value = Evalonoff_trailer(tree, paramlist); break; case TokenType.stage_stmt: Value = Evalstage_stmt(tree, paramlist); break; case TokenType.clear_stmt: Value = Evalclear_stmt(tree, paramlist); break; case TokenType.add_stmt: Value = Evaladd_stmt(tree, paramlist); break; case TokenType.remove_stmt: Value = Evalremove_stmt(tree, paramlist); break; case TokenType.log_stmt: Value = Evallog_stmt(tree, paramlist); break; case TokenType.break_stmt: Value = Evalbreak_stmt(tree, paramlist); break; case TokenType.preserve_stmt: Value = Evalpreserve_stmt(tree, paramlist); break; case TokenType.declare_identifier_clause: Value = Evaldeclare_identifier_clause(tree, paramlist); break; case TokenType.declare_parameter_clause: Value = Evaldeclare_parameter_clause(tree, paramlist); break; case TokenType.declare_function_clause: Value = Evaldeclare_function_clause(tree, paramlist); break; case TokenType.declare_lock_clause: Value = Evaldeclare_lock_clause(tree, paramlist); break; case TokenType.declare_stmt: Value = Evaldeclare_stmt(tree, paramlist); break; case TokenType.return_stmt: Value = Evalreturn_stmt(tree, paramlist); break; case TokenType.switch_stmt: Value = Evalswitch_stmt(tree, paramlist); break; case TokenType.copy_stmt: Value = Evalcopy_stmt(tree, paramlist); break; case TokenType.rename_stmt: Value = Evalrename_stmt(tree, paramlist); break; case TokenType.delete_stmt: Value = Evaldelete_stmt(tree, paramlist); break; case TokenType.edit_stmt: Value = Evaledit_stmt(tree, paramlist); break; case TokenType.run_stmt: Value = Evalrun_stmt(tree, paramlist); break; case TokenType.runpath_stmt: Value = Evalrunpath_stmt(tree, paramlist); break; case TokenType.runoncepath_stmt: Value = Evalrunoncepath_stmt(tree, paramlist); break; case TokenType.compile_stmt: Value = Evalcompile_stmt(tree, paramlist); break; case TokenType.list_stmt: Value = Evallist_stmt(tree, paramlist); break; case TokenType.reboot_stmt: Value = Evalreboot_stmt(tree, paramlist); break; case TokenType.shutdown_stmt: Value = Evalshutdown_stmt(tree, paramlist); break; case TokenType.for_stmt: Value = Evalfor_stmt(tree, paramlist); break; case TokenType.unset_stmt: Value = Evalunset_stmt(tree, paramlist); break; case TokenType.arglist: Value = Evalarglist(tree, paramlist); break; case TokenType.expr: Value = Evalexpr(tree, paramlist); break; case TokenType.or_expr: Value = Evalor_expr(tree, paramlist); break; case TokenType.and_expr: Value = Evaland_expr(tree, paramlist); break; case TokenType.compare_expr: Value = Evalcompare_expr(tree, paramlist); break; case TokenType.arith_expr: Value = Evalarith_expr(tree, paramlist); break; case TokenType.multdiv_expr: Value = Evalmultdiv_expr(tree, paramlist); break; case TokenType.unary_expr: Value = Evalunary_expr(tree, paramlist); break; case TokenType.factor: Value = Evalfactor(tree, paramlist); break; case TokenType.suffix: Value = Evalsuffix(tree, paramlist); break; case TokenType.suffix_trailer: Value = Evalsuffix_trailer(tree, paramlist); break; case TokenType.suffixterm: Value = Evalsuffixterm(tree, paramlist); break; case TokenType.suffixterm_trailer: Value = Evalsuffixterm_trailer(tree, paramlist); break; case TokenType.function_trailer: Value = Evalfunction_trailer(tree, paramlist); break; case TokenType.array_trailer: Value = Evalarray_trailer(tree, paramlist); break; case TokenType.atom: Value = Evalatom(tree, paramlist); break; case TokenType.sci_number: Value = Evalsci_number(tree, paramlist); break; case TokenType.number: Value = Evalnumber(tree, paramlist); break; case TokenType.varidentifier: Value = Evalvaridentifier(tree, paramlist); break; case TokenType.identifier_led_stmt: Value = Evalidentifier_led_stmt(tree, paramlist); break; case TokenType.identifier_led_expr: Value = Evalidentifier_led_expr(tree, paramlist); break; default: Value = Token.Text; break; } return(Value); }
public override bool IsCommandComplete(string command) { char[] commandChars = command.ToCharArray(); int length = commandChars.Length; bool inQuotes = false; bool inCommentToEoln = false; bool waitForMoreTokens = false; char curChar; char prevChar = '\0'; // First, we have to check manually for unterminated string literals because // they are a continuation in the midst of a token, rather than between tokens, // and thus the parser doesn't quite catch them the same way. for (int n = 0; n < length; n++) { curChar = commandChars[n]; switch (curChar) { // Track if we are in a string literal that didn't close, // and make sure it's not a string literal inside a comment, // because those don't count: case '\"': if (!inCommentToEoln) { inQuotes = !(inQuotes); } break; case '/': if (prevChar == '/' && !inQuotes) { inCommentToEoln = true; } break; case '\n': case '\r': inCommentToEoln = false; break; } prevChar = curChar; } // Second, if we aren't in an unterminated literal string, then let // the parser do the rest of the checking by seeing if it reports // Unexpected Token 'EOF', and looking at what it was expecting instead. // - Possible future refactor - // The string comparison of the human-readable message is the only way // to find out if the error is the exact one we're looking for, which // is what the code below does, and that's a bit fragile. // Making it use a more robust check would first require editing the // TinyPG C# source code and changing the way it encodes a ParseError // so it stores that sort of thing as separate pieces of data in its members. if (!inQuotes) { ParseTree parseTree = parser.Parse(command); foreach (ParseError err in parseTree.Errors) { if (err.Message.StartsWith("Unexpected token 'EOF'")) { if (err.Message.Contains("Expected CURLYCLOSE") || err.Message.Contains("Expected BRACKETCLOSE")) { waitForMoreTokens = true; } } else { // If ANY parse errors are NOT of the form "Unexpected Token 'EOF' ... yadda yadda" then that // automatically means we should fail and not continue regardless of whether or not the other // parse errors may have indicated a continuation is needed. We want to let the user see // the error happen instead. waitForMoreTokens = false; break; } } } return((!waitForMoreTokens) && (!inQuotes)); }