diff options
-rw-r--r-- | lang/en/qtype_algebra.php | 1 | ||||
-rw-r--r-- | parser.php | 46 | ||||
-rw-r--r-- | tests/parser_exception_test.php | 51 |
3 files changed, 79 insertions, 19 deletions
diff --git a/lang/en/qtype_algebra.php b/lang/en/qtype_algebra.php index 26b6fe1..819e14b 100644 --- a/lang/en/qtype_algebra.php +++ b/lang/en/qtype_algebra.php @@ -27,6 +27,7 @@ $string['badclosebracket'] = 'Invalid close bracket found'; $string['badequivtype'] = 'Invalid type: can only compare parser terms with other parser terms'; $string['badfuncargs'] = 'Invalid arguments for the function \'{$a}\''; $string['decimal'] = '.'; +$string['exceptionmessage'] = '{$a}'; $string['illegalplusminus'] = 'Found a + or - in an invalid location'; $string['mismatchedbracket'] = 'Mismatched brackets: Open and close bracket pair not of same type \'{$a}\''; $string['mismatchedcloseb'] = 'Mismatched brackets: Close bracket without an open bracket found'; @@ -21,7 +21,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once(__DIR__.'/../../../config.php'); +// require_once(__DIR__.'/../../../config.php'); /** * Helper function which will compare two strings using their length only. @@ -49,6 +49,14 @@ function qtype_algebra_parser_strlen_sort($a, $b) { } /** + * Base class for all the types of exception we throw. + */ +class parser_exception extends moodle_exception { + public function __construct($error) { + parent::__construct('exceptionmessage', 'qtype_algebra', '', $error); + } +} +/** * Class which represents a single term in an algebraic expression. * * A single algebraic term is considered to be either an operation, for example addition, @@ -204,7 +212,7 @@ class qtype_algebra_parser_term { */ public function set_arguments($args) { if (count($args) != $this->_nargs) { - throw new Exception(get_string('nargswrong', 'qtype_algebra', $this->_value)); + throw new parser_exception(get_string('nargswrong', 'qtype_algebra', $this->_value)); } $this->_arguments = $args; } @@ -223,7 +231,7 @@ class qtype_algebra_parser_term { public function check_arguments($exc = true) { $retval = (count($this->_arguments) == $this->_nargs); if ($exc && !$retval) { - throw new Exception(get_string('nargswrong', 'qtype_algebra', $this->_value)); + throw new parser_exception(get_string('nargswrong', 'qtype_algebra', $this->_value)); } else { return $retval; } @@ -317,7 +325,7 @@ class qtype_algebra_parser_term { public function equivalent($expr) { // Check that the argument is also a term. if (!is_a($expr, 'qtype_algebra_parser_term')) { - throw new Exception(get_string('badequivtype', 'qtype_algebra')); + throw new parser_exception(get_string('badequivtype', 'qtype_algebra')); } // Now check that this term is the same as the given term. if (!$this->equals($expr)) { @@ -349,7 +357,7 @@ class qtype_algebra_parser_term { return false; } default: - throw new Exception(get_string('morethantwoargs', 'qtype_algebra')); + throw new parser_exception(get_string('morethantwoargs', 'qtype_algebra')); } } @@ -374,7 +382,7 @@ class qtype_algebra_parser_term { * @return the numerical value of the term given the provided values for the variables */ public function evaluate($params) { - throw new Exception(get_string('noevaluate', 'qtype_algebra', $this->_value)); + throw new parser_exception(get_string('noevaluate', 'qtype_algebra', $this->_value)); } /** @@ -714,7 +722,7 @@ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { return $mult * doubleval($params[$this->_value]); } else { // Found an indefined variable. Cannot evaluate numerically so throw exception. - throw new Exception(get_string('undefinedvariable', 'qtype_algebra', $this->_value)); + throw new parser_exception(get_string('undefinedvariable', 'qtype_algebra', $this->_value)); } } @@ -1153,7 +1161,7 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { */ public function __construct($text) { if (!function_exists($text) and !array_key_exists($text, self::$fnmap)) { - throw new Exception(get_string('undefinedfunction', 'qtype_algebra', $text)); + throw new parser_exception(get_string('undefinedfunction', 'qtype_algebra', $text)); } $formats = array( 'str' => '%s'.$text.'%s'); if (array_key_exists($text, self::$texmap)) { @@ -1188,7 +1196,7 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { */ public function set_arguments($args) { if (count($args) != $this->_nargs) { - throw new Exception(get_string('badfuncargs', 'qtype_algebra', $this->_value)); + throw new parser_exception(get_string('badfuncargs', 'qtype_algebra', $this->_value)); } if (!is_a($args[0], 'qtype_algebra_parser_bracket')) { // Check to see if this function requires a special bracket. @@ -1541,14 +1549,14 @@ class qtype_algebra_parser { if (preg_match(self::$closeb, substr($text, $i), $m)) { // First check that the current parse tree has at least one term. if (count($tree) == 0) { - throw new Exception(get_string('badclosebracket', 'qtype_algebra')); + throw new parser_exception(get_string('badclosebracket', 'qtype_algebra')); } // Now check that the current tree started with a bracket. if (!is_a($tree[0], 'qtype_algebra_parser_bracket')) { - throw new Exception(get_string('mismatchedcloseb', 'qtype_algebra')); + throw new parser_exception(get_string('mismatchedcloseb', 'qtype_algebra')); } else if ($tree[0]->_value != self::$bramap[$m[0]]) { // Check that the open and close bracket are of the same type. - throw new Exception(get_string('mismatchedbracket', 'qtype_algebra', $tree[0]->_value.$m[0])); + throw new parser_exception(get_string('mismatchedbracket', 'qtype_algebra', $tree[0]->_value.$m[0])); } // Append the current tree to the tree one level up on the stack. array_push($stack[count($stack) - 1], $tree); @@ -1578,7 +1586,7 @@ class qtype_algebra_parser { // Check for a variable and throw an exception if undeclared variables are // not allowed and a list of defined variables was passed. if (!empty($revar) and !$undecvars and $token[1] == 'qtype_algebra_parser_variable') { - throw new Exception(get_string('undeclaredvar', 'qtype_algebra', $m[0])); + throw new parser_exception(get_string('undeclaredvar', 'qtype_algebra', $m[0])); } // Check for a zero argument term preceding a variable, function or special and then // add the implicit multiplication. @@ -1594,12 +1602,12 @@ class qtype_algebra_parser { continue 2; } } - throw new Exception(get_string('unknownterm', 'qtype_algebra', substr($text, $i))); + throw new parser_exception(get_string('unknownterm', 'qtype_algebra', substr($text, $i))); } // End while loop over tokens. // If all the open brackets have been closed then the stack will be empty and the // tree will contain the entire parsed expression. if (count($stack) > 0) { - throw new Exception(get_string('mismatchedopenb', 'qtype_algebra')); + throw new parser_exception(get_string('mismatchedopenb', 'qtype_algebra')); } return $this->interpret($tree); } @@ -1655,7 +1663,7 @@ class qtype_algebra_parser { // Otherwise we have found a minus sign indicating a positive or negative quantity... // Check that we do have a number following otherwise generate an exception... if ($i == (count($tree) - 1) or !method_exists($tree[$i + 1], 'set_negative')) { - throw new Exception(get_string('illegalplusminus', 'qtype_algebra')); + throw new parser_exception(get_string('illegalplusminus', 'qtype_algebra')); } // If we have a subtract operation then we need to make the following number negative. if (is_a($tree[$i], 'qtype_algebra_parser_subtract')) { @@ -1681,7 +1689,7 @@ class qtype_algebra_parser { $i++; continue; } else { - throw new Exception(get_string('missingonearg', 'qtype_algebra', $tree[$i]->_value)); + throw new parser_exception(get_string('missingonearg', 'qtype_algebra', $tree[$i]->_value)); } } else if ($tree[$i]->n_args() == 2) { if ($i > 0 and $i < (count($tree) - 1)) { @@ -1691,7 +1699,7 @@ class qtype_algebra_parser { array_splice($tree, $i - 1, 1); continue; } else { - throw new Exception(get_string('missingtwoargs', 'qtype_algebra', $tree[$i]->_value)); + throw new parser_exception(get_string('missingtwoargs', 'qtype_algebra', $tree[$i]->_value)); } } } else { @@ -1704,7 +1712,7 @@ class qtype_algebra_parser { if (count($tree) == 0) { return new qtype_algebra_parser_nullterm; } else if (count($tree) != 1) { - throw new Exception(get_string('notopterm', 'qtype_algebra')); + throw new parser_exception(get_string('notopterm', 'qtype_algebra')); } if ($bracket) { $bracket->set_arguments(array($tree[0])); diff --git a/tests/parser_exception_test.php b/tests/parser_exception_test.php new file mode 100644 index 0000000..d73f766 --- /dev/null +++ b/tests/parser_exception_test.php @@ -0,0 +1,51 @@ +<?php +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. + +/** + * Unit tests for the short answer question definition class. + * + * @package qtype_algebra + * @copyright 2017 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/algebra/tests/helper.php'); +require_once($CFG->dirroot . '/question/type/algebra/parser.php'); + + +/** + * Unit tests for the algebra question parser. + * + * @copyright 2017 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +class qtype_algebra_parser_exception_test extends advanced_testcase { + /** + * Test parsing an invalid exprssion + */ + public function test_parser_invalid() { + $this->expectException('parser_exception'); + $this->expectExceptionMessage('Mismatched brackets: Open bracket without a close bracket found'); + $p = new qtype_algebra_parser; + $expr = $p->parse('sin(2x) + cos('); + } +} |