Added 'finally' to try/catch block
This commit is contained in:
@@ -41,7 +41,7 @@ namespace chaiscript
|
|||||||
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_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, Try, Catch, Method, Attr_Decl }; };
|
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl }; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper lookup to get the name of each node type
|
* Helper lookup to get the name of each node type
|
||||||
@@ -50,7 +50,7 @@ namespace chaiscript
|
|||||||
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_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", "Try", "Catch", "Method", "Attr_Decl"};
|
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl"};
|
||||||
|
|
||||||
return token_types[tokentype];
|
return token_types[tokentype];
|
||||||
}
|
}
|
||||||
|
@@ -609,12 +609,20 @@ namespace chaiscript
|
|||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
}
|
}
|
||||||
catch (const Eval_Error &) {
|
catch (const Eval_Error &) {
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e) {
|
catch (const std::exception &e) {
|
||||||
Boxed_Value except = Boxed_Value(boost::ref(e));
|
Boxed_Value except = Boxed_Value(boost::ref(e));
|
||||||
for (unsigned int i = 1; i < node->children.size(); ++i) {
|
|
||||||
|
unsigned int end_point = node->children.size();
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
end_point = node->children.size() - 1;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 1; i < end_point; ++i) {
|
||||||
TokenPtr catch_block = node->children[i];
|
TokenPtr catch_block = node->children[i];
|
||||||
|
|
||||||
if (catch_block->children.size() == 1) {
|
if (catch_block->children.size() == 1) {
|
||||||
@@ -636,6 +644,9 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
|
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
|
||||||
} catch (const bad_boxed_cast &) {
|
} catch (const bad_boxed_cast &) {
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
|
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
|
||||||
}
|
}
|
||||||
@@ -645,6 +656,9 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
|
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
|
||||||
}
|
}
|
||||||
@@ -674,6 +688,9 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
|
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
|
||||||
} catch (const bad_boxed_cast &) {
|
} catch (const bad_boxed_cast &) {
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
|
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
|
||||||
}
|
}
|
||||||
@@ -683,15 +700,24 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
|
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||||
|
retval = eval_token(ss, node->children.back()->children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
ss.pop_scope();
|
ss.pop_scope();
|
||||||
|
|
||||||
|
@@ -983,6 +983,17 @@ namespace chaiscript
|
|||||||
has_matches = true;
|
has_matches = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (Eol());
|
||||||
|
if (Keyword("finally", false)) {
|
||||||
|
int finally_stack_top = match_stack.size();
|
||||||
|
|
||||||
|
while (Eol());
|
||||||
|
|
||||||
|
if (!Block()) {
|
||||||
|
throw Eval_Error("Incomplete 'finally' block", File_Position(line, col), filename);
|
||||||
|
}
|
||||||
|
build_match(Token_Type::Finally, finally_stack_top);
|
||||||
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Try, prev_stack_top);
|
build_match(Token_Type::Try, prev_stack_top);
|
||||||
}
|
}
|
||||||
|
19
unittests/exception_finally.chai
Normal file
19
unittests/exception_finally.chai
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
try {
|
||||||
|
throw(3)
|
||||||
|
}
|
||||||
|
catch(x) {
|
||||||
|
print(x)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
print("Finally #1")
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
print("Safe")
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
print("Caught")
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
print("Finally #2")
|
||||||
|
}
|
4
unittests/exception_finally.txt
Normal file
4
unittests/exception_finally.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
3
|
||||||
|
Finally #1
|
||||||
|
Safe
|
||||||
|
Finally #2
|
Reference in New Issue
Block a user