diff --git a/chaiscript/chaiscript.hpp b/chaiscript/chaiscript.hpp index 090af6d..87a1942 100644 --- a/chaiscript/chaiscript.hpp +++ b/chaiscript/chaiscript.hpp @@ -39,12 +39,14 @@ namespace chaiscript */ class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, Expression, Comparison, Additive, Multiplicative, Negate, Not, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String, - Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair }; }; + Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range, + Inline_Range }; }; const char *token_type_to_string(int tokentype) { const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", "Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String", - "Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair" }; + "Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range", + "Inline_Range" }; return token_types[tokentype]; } diff --git a/chaiscript/chaiscript_eval.hpp b/chaiscript/chaiscript_eval.hpp index a438692..2dd55db 100644 --- a/chaiscript/chaiscript_eval.hpp +++ b/chaiscript/chaiscript_eval.hpp @@ -253,6 +253,56 @@ namespace chaiscript } } break; + case (Token_Type::Inline_Range) : { + try { + retval = dispatch(ss.get_function("Vector"), dispatchkit::Param_List_Builder()); + if (node->children.size() > 0) { + dispatchkit::Boxed_Value range_iter = dispatch(ss.get_function("clone"), dispatchkit::Param_List_Builder() << eval_token(ss, node->children[0]->children[0]->children[0])); + dispatchkit::Boxed_Value range_stop = eval_token(ss, node->children[0]->children[0]->children[1]); + + dispatchkit::Boxed_Value not_equal; + + bool cond = true; + try { + not_equal = dispatch(ss.get_function("!="), dispatchkit::Param_List_Builder() << range_iter << range_stop); + cond = dispatchkit::boxed_cast(not_equal); + } + catch (std::exception &e) { + throw EvalError("Range values missing != comparison", node->children[0]); + } + + dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << range_iter); + not_equal = dispatch(ss.get_function("!="), dispatchkit::Param_List_Builder() << range_iter << range_stop); + try { + cond = dispatchkit::boxed_cast(not_equal); + } + catch (std::exception &e) { + throw EvalError("Range values missing != comparison", node->children[0]); + } + while (cond) { + try { + range_iter = dispatch(ss.get_function("clone"), dispatchkit::Param_List_Builder() << range_iter); + range_iter = dispatch(ss.get_function("++"), dispatchkit::Param_List_Builder() << range_iter); + dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << range_iter); + not_equal = dispatch(ss.get_function("!="), dispatchkit::Param_List_Builder() << range_iter << range_stop); + try { + cond = dispatchkit::boxed_cast(not_equal); + } + catch (std::exception &e) { + throw EvalError("Range values missing != comparison", node->children[0]); + } + } + catch (const dispatchkit::dispatch_error &inner_e) { + throw EvalError("Can not find appropriate range increment", node->children[0]->children[i]); + } + } + } + } + catch (const dispatchkit::dispatch_error &e) { + throw EvalError("Can not find appropriate 'Vector()'", node); + } + } + break; case (Token_Type::Inline_Map) : { try { retval = dispatch(ss.get_function("Map"), dispatchkit::Param_List_Builder()); diff --git a/chaiscript/chaiscript_parser.hpp b/chaiscript/chaiscript_parser.hpp index c7f0655..7b56276 100644 --- a/chaiscript/chaiscript_parser.hpp +++ b/chaiscript/chaiscript_parser.hpp @@ -518,7 +518,7 @@ namespace chaiscript bool retval = Symbol_(s); if (retval) { //todo: fix this. Hacky workaround for preventing substring matches - if ((input_pos != input_end) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '='))) { + if ((input_pos != input_end) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '=') || (*input_pos == '.'))) { input_pos = start; col = prev_col; line = prev_line; @@ -536,7 +536,7 @@ namespace chaiscript int prev_line = line; if (Symbol_(s)) { //todo: fix this. Hacky workaround for preventing substring matches - if ((input_pos != input_end) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '='))) { + if ((input_pos != input_end) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '=') || (*input_pos == '.'))) { input_pos = start; col = prev_col; line = prev_line; @@ -618,7 +618,11 @@ namespace chaiscript int prev_stack_top = match_stack.size(); - if (Map_Pair()) { + if (Value_Range()) { + retval = true; + build_match(Token_Type::Arg_List, prev_stack_top); + } + else if (Map_Pair()) { retval = true; if (Char(',')) { do { @@ -967,7 +971,10 @@ namespace chaiscript throw Parse_Error("Missing closing square bracket", File_Position(line, col), filename); } if ((prev_stack_top != match_stack.size()) && (match_stack.back()->children.size() > 0)) { - if (match_stack.back()->children[0]->identifier == Token_Type::Map_Pair) { + if (match_stack.back()->children[0]->identifier == Token_Type::Value_Range) { + build_match(Token_Type::Inline_Range, prev_stack_top); + } + else if (match_stack.back()->children[0]->identifier == Token_Type::Map_Pair) { build_match(Token_Type::Inline_Map, prev_stack_top); } else { @@ -1210,6 +1217,33 @@ namespace chaiscript return retval; } + bool Value_Range() { + bool retval = false; + + unsigned int prev_stack_top = match_stack.size(); + std::string::iterator prev_pos = input_pos; + int prev_col = col; + + if (Expression()) { + if (Symbol("..")) { + retval = true; + if (!Expression()) { + throw Parse_Error("Incomplete value range", File_Position(line, col), filename); + } + + build_match(Token_Type::Value_Range, prev_stack_top); + } + else { + input_pos = prev_pos; + col = prev_col; + while (prev_stack_top != match_stack.size()) { + match_stack.pop_back(); + } + } + } + + return retval; + } bool Equation() { bool retval = false;