The new parser is designed to be used in two ways.  First, you can use
it within your perl code when writing problems as a means of making it
easier to handle formulas, and in particular, to genarate be able to
use a single object to produce numeric values, TeX output and answer
strings.  This avoids having to type a function three different ways
(which makes maintaining a problem much harder).  Since the parser
also included vector and complex arthimatic, it is easier to work with
these types of values as well.

The second reason for the parser is to use it to process student
input.  This is accomplished through special answer checkers that are
checkers).  Checkers are available for all the types of values that
the parser can produce (numbers, complex numbers, infinities, points,
vectors, intervals, unions, formulas, lists of numbers, lists of
points, lists of intervals, lists of formulas returning numbers, lists
of formulas returning points, and so on).

To use one of these checkers, simply call the ->cmp method of the
object that represents the correct answer.  For example:

$n = Real(sqrt(2)); ANS($n->cmp);

will produce an answer checker that matches the square root of two.
Similarly,

ANS(Vector(1,2,3)->cmp);

matches the vector <1,2,3> (or any computation that produces it, e.g.,
i+2j+3k, or <4,4,4>-<3,2,1>), while

ANS(Interval("(-inf,3]")->cmp);

matches the given interval.  Other examples include:

ANS(Infinity->cmp);
ANS(String('NONE')->cmp);
ANS(Union("(-inf,$a) U ($a,inf)")->cmp);

and so on.

Formulas are handled in the same way:

ANS(Formula("x+1")->cmp);

$a = random(-5,5,1);$b = random(-5,5,1); $x = random(-5,5,1);$f = Formula("x^2 + $a x +$b")->reduce;
ANS($f->cmp); ANS($f->eval(x=>$x)->cmp);$x = Formula('x');
ANS((1+$a*$x)->cmp);

Context("Vector")->variables->are(t=>'Real');
$v = Formula("<t,t^2,t^3>");$t = random(-5,5,1);
ANS($v->cmp); ANS($v->eval(t=>$t)->cmp); and so on. Lists of items can be checked as easily: ANS(List(1,-1,0)->cmp); ANS(List(Point($a,$b),Point($a,-$b))->cmp); ANS(List(Vector(1,0,0),Vector(0,1,1))->cmp); ANS(Compute("(-inf,2),(4,5)")->cmp); # easy way to get list of intervals ANS(Formula("x, x+1, x^2-1")->cmp); ANS(Formula("<x,2x>,<x,-2x>,<0,x>")->cmp); ANS(List('NONE')->cmp); and so on. The last example may seem strange, as you could have used ANS(String('NONE')->cmp), but there is a reason for using this type of construction. You might be asking for one or more numbers (or points, or whatever) or the word 'NONE' of there are no numbers (or points). If you used String('NONE')->cmp, the student would get an error message about a type mismatch if he entered a list of numbers, but with List('NONE')->cmp, he will get appropriate error messages for the wrong entries in the list. It is often appropriate to use the list checker in this way even when the correct answer is a single value, if the student might type a list of answers. On the other hand, using the list checker has its disadvantages. For example, if you use ANS(Interval("(-inf,3]")->cmp); and the student enters (-inf,3), she will get a message indicating that the type of interval is incorrect, while that would not be the case if ANS(List(Interval("(-inf,3]"))->cmp); were used. (This is because the student doesn't know how many intervals there are, so saying that the type of interval is wrong would inform her that there is only one.) The rule of thumb is: the individual checkers can give more detailed information about what is wrong with the student's answer; the list checker allows a wider range of answers to be given without giving away how many answers there are. If the student knows there's only one, use the individual checker; if there may or may not be more than one, use the list checker. Note that you can form lists of formulas as well. The following all produce the same answer checker: ANS(List(Formula("x+1"),Formula("x-1"))->cmp); ANS(Formula("x+1,x-1")->cmp); # easier$f = Formula("x+1"); $g = Formula("x-1"); ANS(List($f,$g)->cmp);$x = Formula('x');
ANS(List($x+1,$x-1)->cmp);

See the files in webwork2/doc/parser/problems for more
examples of using the parser's answer checkers.

CONTROLLING THE DETAILS OF THE ANSWER CHECKERS:

The action of the answer checkers can be modified by passing flags to
the cmp() method.  For example:

ANS(Real(pi)->cmp(showTypeWarnings=>0));

will prevent the answer checker from reporting errors due to the
student entering in the wrong type of answer (say a vector rather than
a number).

There are a number of flags common to all the checkers:

showTypeWarnings=>1 or 0    show/don't show messages about student
answers not being of the right type.
(default: 1)

showEqualErrors=>1 or 0    show/don't show messages produced by
trying to compare the professor and
student values for equality, e.g.,
conversion errors between types.
(default: 1)

ignoreStrings=>1 or 0      show/don't show type mismatch errors
produced by strings (so that 'NONE' will
not cause a type mismatch in a checker
looking for a list of numbers, for example).
(default: 1)

In addition to these, the individual types have their own flags:

Real()->cmp:

ignoreInfinity=>1 or 0    Don't report type mismatches if the
student enters an infinity.
(default: 1)

String()->cmp:

typeMatch=>value          Specifies the type of object that
the student should be allowed to enter
(default: 'Value::Real')

Point()->cmp:

showDimensionHints=>1 or 0    show/don't show messages about the
wrong number of coordinates.
(default: 1)

showCoordinateHints=>1 or 0  show/don't show message about
which coordinates are right.
(default: 1)

Vector()->cmp:

showDimensionHints=>1 or 0    show/don't show messages about the
wrong number of coordinates.
(default: 1)

showCoordinateHints=>1 or 0  show/don't show message about
which coordinates are right.
(default: 1)

promotePoints=>1 or 0     do/don't allow the student to
enter a point rather than a vector.
(default: 1)

parallel=>1 or 0     Mark the answer as correct if it
is parallel to the professor's answer.
Note that a value of 1 forces
showCoordinateHints to be 0.
(default: 0)

sameDirection=>1 or 0        During a parallel check, mark the
answer as correct only if it is in
the same (not the opposite)
(default: 0)

Matrix()->cmp:

showDimensionHints=>1 or 0    show/don't show messages about the
wrong number of coordinates.
(default: 1)

The default for showEqualErrors is set to 0 for Matrices, since
these errors usually are dimension errors, and that is handled
separately (and after the equality check).

Interval()->cmp:

showEndpointHints=>1 or 0    do/don't show messages about which
endpoints are correct.
(default: 1)

showEndTypeHints=>1 or 0    do/don't show messages about
whether the open/closed status of
the enpoints are correct (only
shown when the endpoints themselves
are correct).
(default: 1)

Union()->cmp and
List()->cmp:

all the flags from the Real()->cmp, plus:

showHints=>1 or 0        do/don't show messages about which
entries are incorrect.
(default:  $showPartialCorrectAnswers) showLengthHints=>1 or 0 do/don't show messages about having the correct number of entries (only shown when all the student answers are correct but there are more needed, or all the correct answsers are among the ones given, but some extras were given). (default:$showPartialCorrectAnswers)

partialCredit=>1 or 0    do/don't give partial credit for when
some answers are right, but not all.
(default:  $showPartialCorrectAnswers) (currently the default is 0 since WW can't handle partial credit properly). ordered=>1 or 0 give credit only if the student answers are in the same order as the professor's answers. (default: 0) entry_type=>'a (name)' The string to use in error messages about type mismatches. (default: dynamically determined from list) list_type=>'a (name)' The string to use in error messages about numbers of entries in the list. (default: dynamically determined from list) typeMatch=>value Specifies the type of object that the student should be allowed to enter in the list (determines what constitutes a type mismatch error). (default: dynamically determined from list) requireParenMatch=>1 or 0 Do/don't require the parentheses in the student's answer to match those in the professor's answer exactly. (default: 1) removeParens=>1 or 0 Do/don't remove the parentheses from the professor's list as part of the correct answer string. This is so that if you use List() to create the list (which doesn't allow you to control the parens directly), you can still get a list with no parentheses. (default: 0 for List() and 1 for Formula()) Formula()->cmp: The flags for formulas are dependent on the type of the result of the formula. If the result is a list or union, it gets the flags for that type above, otherwise it gets that flags of the Real type above. More flags need to be added in order to allow more control over the answer checkers to give the full flexibility of the traditional WeBWorK answer checkers. Note that some things, like whether trig functions are allowed in the answer, are controlled through the Context() rather than the answer checker itself. For example, Context()->functions->undefine('sin','cos','tan'); would remove those three functions from use. (One would need to remove cot, sec, csc, arcsin, asin, etc., to do this properly; there could be a function call to do this.) Similarly, which arithmetic operations are available is controlled through Context()->operations. The tolerances used in comparing numbers are part of the Context as well. You can set these via: Context()->flags->set( tolerance => .0001, # the relative or absolute tolerance tolType => 'relative', # or 'absolute' zeroLevel => 1E-14, # when to use zeroLevelTol zeroLevelTol => 1E-12, # smaller than this matches zero # when one of the two is less # than zeroLevel limits => [-2,2], # limits for variables in formulas num_points => 5, # the number of test points ); [These need to be handled better.] Note that for testing formulas, you can override the limits and num_points settings by setting these fields of the formula itself:$f = Formula("sqrt(x-10)");
$f->{limits} = [10,12];$f = Formula("log(xy)");
$f->{limits} = [[.1,2],[.1,2]]; # x and y limits You can also specify the test points explicitly:$f = Formula("sqrt(x-10)");
$f->{test_points} = [,[11.5],];$f = Formula("log(xy)");
\$f->{test_points} = [[.1,.1],[.1,.5],[.1,.75],
[.5,.1],[.5,.5],[.5,.75]];

[There still needs to be a means of handling the tolerances similarly,
and through the ->cmp() call itself.]