Implement support for handling exceptions in user scripts

This commit is contained in:
Gunnar Beutner 2017-06-12 09:12:43 +02:00 committed by Michael Friedrich
parent deb7855dc1
commit f9feb41877
6 changed files with 72 additions and 5 deletions

View File

@ -851,7 +851,7 @@ Example:
var s = String(3) /* Sets s to "3". */
## <a id="throw"></a> Exceptions
## <a id="throw"></a> Throwing Exceptions
Built-in commands may throw exceptions to signal errors such as invalid arguments. User scripts can throw exceptions
using the `throw` keyword.
@ -860,7 +860,20 @@ Example:
throw "An error occurred."
There is currently no way for scripts to catch exceptions.
## <a id="try-except"></a> Handling Exceptions
Exceptions can be handled using the `try` and `except` keywords. When an exception occurs while executing code in the
`try` clause no further statements in the `try` clause are evaluated and the `except` clause is executed instead.
Example:
try {
throw "Test"
log("This statement won't get executed.")
} except {
log("An error occurred in the try clause.")
}
## <a id="breakpoints"></a> Breakpoints
@ -920,7 +933,7 @@ These keywords are reserved and must not be used as constants or custom attribut
template
include
include_recursive
ignore_on_error
include_zones
library
null
true
@ -928,7 +941,13 @@ These keywords are reserved and must not be used as constants or custom attribut
const
var
this
globals
locals
use
default
ignore_on_error
current_filename
current_line
apply
to
where
@ -937,12 +956,16 @@ These keywords are reserved and must not be used as constants or custom attribut
ignore
function
return
break
continue
for
if
else
while
throw
try
except
in
current_filename
current_line
You can escape reserved keywords using the `@` character. The following example
tries to set `vars.include` which references a reserved keyword and generates

View File

@ -262,6 +262,8 @@ const std::vector<String>& ConfigWriter::GetKeywords(void)
keywords.push_back("else");
keywords.push_back("while");
keywords.push_back("throw");
keywords.push_back("try");
keywords.push_back("except");
}
return keywords;

View File

@ -197,6 +197,8 @@ if return T_IF;
else return T_ELSE;
while return T_WHILE;
throw return T_THROW;
try return T_TRY;
except return T_EXCEPT;
ignore_on_error return T_IGNORE_ON_ERROR;
current_filename return T_CURRENT_FILENAME;
current_line return T_CURRENT_LINE;

View File

@ -172,6 +172,8 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%token T_ELSE "else (T_ELSE)"
%token T_WHILE "while (T_WHILE)"
%token T_THROW "throw (T_THROW)"
%token T_TRY "try (T_TRY)"
%token T_EXCEPT "except (T_EXCEPT)"
%token T_FOLLOWS "=> (T_FOLLOWS)"
%token T_NULLARY_LAMBDA_BEGIN "{{ (T_NULLARY_LAMBDA_BEGIN)"
%token T_NULLARY_LAMBDA_END "}} (T_NULLARY_LAMBDA_END)"
@ -666,6 +668,10 @@ lterm: T_LIBRARY rterm
{
$$ = new ThrowExpression($2, false, @$);
}
| T_TRY rterm_scope T_EXCEPT rterm_scope
{
$$ = new TryExceptExpression($2, $4, @$);
}
| rterm_side_effect
;

View File

@ -941,3 +941,16 @@ ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin
return Empty;
}
ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
try {
ExpressionResult tryResult = m_TryBody->Evaluate(frame, dhint);
CHECK_RESULT(tryResult);
} catch (const std::exception& ex) {
ExpressionResult exceptResult = m_ExceptBody->Evaluate(frame, dhint);
CHECK_RESULT(exceptResult);
}
return Empty;
}

View File

@ -1027,6 +1027,27 @@ private:
Expression *m_Name;
};
class I2_CONFIG_API TryExceptExpression : public DebuggableExpression
{
public:
TryExceptExpression(Expression *tryBody, Expression *exceptBody, const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo), m_TryBody(tryBody), m_ExceptBody(exceptBody)
{ }
~TryExceptExpression(void)
{
delete m_TryBody;
delete m_ExceptBody;
}
protected:
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
private:
Expression *m_TryBody;
Expression *m_ExceptBody;
};
}
#endif /* EXPRESSION_H */