Added 'finally' to try/catch block

This commit is contained in:
Jonathan Turner
2009-09-19 18:12:22 +00:00
parent 7c244d25b5
commit c5f837fd19
5 changed files with 63 additions and 3 deletions

View File

@@ -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,
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,
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
@@ -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",
"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",
"Inline_Range", "Annotation", "Try", "Catch", "Method", "Attr_Decl"};
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl"};
return token_types[tokentype];
}

View File

@@ -609,12 +609,20 @@ namespace chaiscript
retval = eval_token(ss, node->children[0]);
}
catch (const Eval_Error &) {
if (node->children.back()->identifier == Token_Type::Finally) {
eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();
throw;
}
catch (const std::exception &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];
if (catch_block->children.size() == 1) {
@@ -636,6 +644,9 @@ namespace chaiscript
try {
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
} catch (const bad_boxed_cast &) {
if (node->children.back()->identifier == Token_Type::Finally) {
eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
}
@@ -645,6 +656,9 @@ namespace chaiscript
}
}
else {
if (node->children.back()->identifier == Token_Type::Finally) {
eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
}
@@ -674,6 +688,9 @@ namespace chaiscript
try {
guard = boxed_cast<bool>(eval_token(ss, catch_block->children[1]));
} catch (const bad_boxed_cast &) {
if (node->children.back()->identifier == Token_Type::Finally) {
eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();
throw Eval_Error("Guard condition not boolean", catch_block->children[1]);
}
@@ -683,15 +700,24 @@ namespace chaiscript
}
}
else {
if (node->children.back()->identifier == Token_Type::Finally) {
eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();
throw Eval_Error("Internal error: catch block size unrecognized", catch_block);
}
}
}
catch (...) {
if (node->children.back()->identifier == Token_Type::Finally) {
eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();
throw;
}
if (node->children.back()->identifier == Token_Type::Finally) {
retval = eval_token(ss, node->children.back()->children[0]);
}
ss.pop_scope();

View File

@@ -983,6 +983,17 @@ namespace chaiscript
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);
}

View 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")
}

View File

@@ -0,0 +1,4 @@
3
Finally #1
Safe
Finally #2