Add in-string eval
This commit is contained in:
parent
f369afed77
commit
5092713876
@ -28,7 +28,7 @@ namespace chaiscript
|
|||||||
/**
|
/**
|
||||||
* Types of AST nodes available to the parser and eval
|
* Types of AST nodes available to the parser and eval
|
||||||
*/
|
*/
|
||||||
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||||
Expression, Comparison, Additive, Multiplicative, Negate, Not, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
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, Value_Range,
|
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||||
Inline_Range, Annotation }; };
|
Inline_Range, Annotation }; };
|
||||||
@ -37,7 +37,7 @@ namespace chaiscript
|
|||||||
* Helper lookup to get the name of each node type
|
* Helper lookup to get the name of each node type
|
||||||
*/
|
*/
|
||||||
const char *token_type_to_string(int tokentype) {
|
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",
|
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||||
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
"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", "Value_Range",
|
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||||
"Inline_Range", "Annotation"};
|
"Inline_Range", "Annotation"};
|
||||||
|
@ -116,6 +116,15 @@ namespace chaiscript
|
|||||||
Boxed_Value eval_quoted_string(Eval_System &ss, const TokenPtr &node) {
|
Boxed_Value eval_quoted_string(Eval_System &ss, const TokenPtr &node) {
|
||||||
//return const_var(node->text);
|
//return const_var(node->text);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ((node->text.size() > 0) && (node->text[0] == '$')) {
|
||||||
|
node->text.erase(0, 1);
|
||||||
|
Param_List_Builder plb;
|
||||||
|
plb << node->text;
|
||||||
|
|
||||||
|
return ss.call_function("eval", plb);
|
||||||
|
}
|
||||||
|
*/
|
||||||
if (!node->is_cached) {
|
if (!node->is_cached) {
|
||||||
cache_const(ss, node, const_var(node->text));
|
cache_const(ss, node, const_var(node->text));
|
||||||
}
|
}
|
||||||
@ -468,6 +477,43 @@ namespace chaiscript
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates a function call, starting with its arguments. Does NOT change scope.
|
||||||
|
*/
|
||||||
|
template <typename Eval_System>
|
||||||
|
Boxed_Value eval_inplace_fun_call(Eval_System &ss, const TokenPtr &node) {
|
||||||
|
Param_List_Builder plb;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if ((node->children.size() > 1) && (node->children[1]->identifier == Token_Type::Arg_List)) {
|
||||||
|
for (i = 0; i < node->children[1]->children.size(); ++i) {
|
||||||
|
plb << eval_token(ss, node->children[1]->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Boxed_Value fn = eval_token(ss, node->children[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Boxed_Value retval = (*boxed_cast<Proxy_Function >(fn))(plb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
catch(const dispatch_error &e){
|
||||||
|
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
|
||||||
|
}
|
||||||
|
catch(Return_Value &rv) {
|
||||||
|
return rv.retval;
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Eval_Error &ee) {
|
||||||
|
throw Eval_Error(ee.reason, node->children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a method/attributes invocation
|
* Evaluates a method/attributes invocation
|
||||||
*/
|
*/
|
||||||
@ -870,6 +916,10 @@ namespace chaiscript
|
|||||||
return eval_fun_call(ss, node);
|
return eval_fun_call(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case (Token_Type::Inplace_Fun_Call) :
|
||||||
|
return eval_inplace_fun_call(ss, node);
|
||||||
|
break;
|
||||||
|
|
||||||
case (Token_Type::Dot_Access) :
|
case (Token_Type::Dot_Access) :
|
||||||
return eval_dot_access(ss, node);
|
return eval_dot_access(ss, node);
|
||||||
break;
|
break;
|
||||||
|
@ -323,7 +323,85 @@ namespace chaiscript
|
|||||||
if (Quoted_String_()) {
|
if (Quoted_String_()) {
|
||||||
std::string match;
|
std::string match;
|
||||||
bool is_escaped = false;
|
bool is_escaped = false;
|
||||||
for (std::string::iterator s = start + 1, end = input_pos - 1; s != end; ++s) {
|
bool is_interpolated = false;
|
||||||
|
bool saw_interpolation_marker = false;
|
||||||
|
int prev_stack_top = match_stack.size();
|
||||||
|
|
||||||
|
//for (std::string::iterator s = start + 1, end = input_pos - 1; s != end; ++s) {
|
||||||
|
std::string::iterator s = start + 1, end = input_pos - 1;
|
||||||
|
|
||||||
|
while (s != end) {
|
||||||
|
if (saw_interpolation_marker) {
|
||||||
|
if (*s == '{') {
|
||||||
|
//We've found an interpolation point
|
||||||
|
|
||||||
|
if (is_interpolated) {
|
||||||
|
//If we've seen previous interpolation, add on instead of making a new one
|
||||||
|
TokenPtr plus(new Token("+", Token_Type::Str, filename, -1, -1, -1, -1));
|
||||||
|
match_stack.push_back(plus);
|
||||||
|
|
||||||
|
TokenPtr t(new Token(match, Token_Type::Quoted_String, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(t);
|
||||||
|
|
||||||
|
build_match(Token_Type::Additive, prev_stack_top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TokenPtr t(new Token(match, Token_Type::Quoted_String, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
//We've finished with the part of the string up to this point, so clear it
|
||||||
|
match = "";
|
||||||
|
|
||||||
|
TokenPtr plus(new Token("+", Token_Type::Str, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(plus);
|
||||||
|
|
||||||
|
std::string eval_match;
|
||||||
|
|
||||||
|
++s;
|
||||||
|
while ((*s != '}') && (s != end)) {
|
||||||
|
eval_match.push_back(*s);
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
if (*s == '}') {
|
||||||
|
is_interpolated = true;
|
||||||
|
++s;
|
||||||
|
|
||||||
|
int tostr_stack_top = match_stack.size();
|
||||||
|
|
||||||
|
TokenPtr tostr(new Token("to_string", Token_Type::Id, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(tostr);
|
||||||
|
|
||||||
|
int ev_stack_top = match_stack.size();
|
||||||
|
|
||||||
|
TokenPtr ev(new Token("eval", Token_Type::Id, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(ev);
|
||||||
|
|
||||||
|
int arg_stack_top = match_stack.size();
|
||||||
|
|
||||||
|
TokenPtr t(new Token(eval_match, Token_Type::Quoted_String, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(t);
|
||||||
|
|
||||||
|
build_match(Token_Type::Arg_List, arg_stack_top);
|
||||||
|
|
||||||
|
build_match(Token_Type::Inplace_Fun_Call, ev_stack_top);
|
||||||
|
|
||||||
|
build_match(Token_Type::Arg_List, ev_stack_top);
|
||||||
|
|
||||||
|
build_match(Token_Type::Fun_Call, tostr_stack_top);
|
||||||
|
|
||||||
|
build_match(Token_Type::Additive, prev_stack_top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw Eval_Error("Unclosed in-string eval", File_Position(prev_line, prev_col), filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
match.push_back('$');
|
||||||
|
}
|
||||||
|
saw_interpolation_marker = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
if (*s == '\\') {
|
if (*s == '\\') {
|
||||||
if (is_escaped) {
|
if (is_escaped) {
|
||||||
match.push_back('\\');
|
match.push_back('\\');
|
||||||
@ -343,17 +421,34 @@ namespace chaiscript
|
|||||||
case ('t') : match.push_back('\t'); break;
|
case ('t') : match.push_back('\t'); break;
|
||||||
case ('\'') : match.push_back('\''); break;
|
case ('\'') : match.push_back('\''); break;
|
||||||
case ('\"') : match.push_back('\"'); break;
|
case ('\"') : match.push_back('\"'); break;
|
||||||
|
case ('$') : match.push_back('$'); break;
|
||||||
default: throw Eval_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
|
default: throw Eval_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (*s == '$') {
|
||||||
|
saw_interpolation_marker = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
match.push_back(*s);
|
match.push_back(*s);
|
||||||
}
|
}
|
||||||
is_escaped = false;
|
is_escaped = false;
|
||||||
}
|
}
|
||||||
|
++s;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (is_interpolated) {
|
||||||
|
TokenPtr plus(new Token("+", Token_Type::Str, filename, -1, -1, -1, -1));
|
||||||
|
match_stack.push_back(plus);
|
||||||
|
|
||||||
TokenPtr t(new Token(match, Token_Type::Quoted_String, filename, prev_line, prev_col, line, col));
|
TokenPtr t(new Token(match, Token_Type::Quoted_String, filename, prev_line, prev_col, line, col));
|
||||||
match_stack.push_back(t);
|
match_stack.push_back(t);
|
||||||
|
|
||||||
|
build_match(Token_Type::Additive, prev_stack_top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TokenPtr t(new Token(match, Token_Type::Quoted_String, filename, prev_line, prev_col, line, col));
|
||||||
|
match_stack.push_back(t);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user