Merge pull request #5348 from Icinga/feature/try-except

Implement support for handling exceptions in user scripts
This commit is contained in:
Michael Friedrich 2017-06-13 16:21:54 +02:00 committed by GitHub
commit cc82e634c6
6 changed files with 72 additions and 5 deletions

View File

@ -851,7 +851,7 @@ Example:
var s = String(3) /* Sets s to "3". */ 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 Built-in commands may throw exceptions to signal errors such as invalid arguments. User scripts can throw exceptions
using the `throw` keyword. using the `throw` keyword.
@ -860,7 +860,20 @@ Example:
throw "An error occurred." 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 ## <a id="breakpoints"></a> Breakpoints
@ -920,7 +933,7 @@ These keywords are reserved and must not be used as constants or custom attribut
template template
include include
include_recursive include_recursive
ignore_on_error include_zones
library library
null null
true true
@ -928,7 +941,13 @@ These keywords are reserved and must not be used as constants or custom attribut
const const
var var
this this
globals
locals
use use
default
ignore_on_error
current_filename
current_line
apply apply
to to
where where
@ -937,12 +956,16 @@ These keywords are reserved and must not be used as constants or custom attribut
ignore ignore
function function
return return
break
continue
for for
if if
else else
while
throw
try
except
in in
current_filename
current_line
You can escape reserved keywords using the `@` character. The following example You can escape reserved keywords using the `@` character. The following example
tries to set `vars.include` which references a reserved keyword and generates 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("else");
keywords.push_back("while"); keywords.push_back("while");
keywords.push_back("throw"); keywords.push_back("throw");
keywords.push_back("try");
keywords.push_back("except");
} }
return keywords; return keywords;

View File

@ -197,6 +197,8 @@ if return T_IF;
else return T_ELSE; else return T_ELSE;
while return T_WHILE; while return T_WHILE;
throw return T_THROW; throw return T_THROW;
try return T_TRY;
except return T_EXCEPT;
ignore_on_error return T_IGNORE_ON_ERROR; ignore_on_error return T_IGNORE_ON_ERROR;
current_filename return T_CURRENT_FILENAME; current_filename return T_CURRENT_FILENAME;
current_line return T_CURRENT_LINE; 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_ELSE "else (T_ELSE)"
%token T_WHILE "while (T_WHILE)" %token T_WHILE "while (T_WHILE)"
%token T_THROW "throw (T_THROW)" %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_FOLLOWS "=> (T_FOLLOWS)"
%token T_NULLARY_LAMBDA_BEGIN "{{ (T_NULLARY_LAMBDA_BEGIN)" %token T_NULLARY_LAMBDA_BEGIN "{{ (T_NULLARY_LAMBDA_BEGIN)"
%token T_NULLARY_LAMBDA_END "}} (T_NULLARY_LAMBDA_END)" %token T_NULLARY_LAMBDA_END "}} (T_NULLARY_LAMBDA_END)"
@ -666,6 +668,10 @@ lterm: T_LIBRARY rterm
{ {
$$ = new ThrowExpression($2, false, @$); $$ = new ThrowExpression($2, false, @$);
} }
| T_TRY rterm_scope T_EXCEPT rterm_scope
{
$$ = new TryExceptExpression($2, $4, @$);
}
| rterm_side_effect | rterm_side_effect
; ;

View File

@ -941,3 +941,16 @@ ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin
return Empty; 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; 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 */ #endif /* EXPRESSION_H */