--- loncom/xml/algebra/AlgParser.pm 2005/06/09 02:35:55 1.14 +++ loncom/xml/algebra/AlgParser.pm 2009/02/13 17:20:23 1.18 @@ -1,4 +1,4 @@ - +# $Id: AlgParser.pm,v 1.18 2009/02/13 17:20:23 bisitz Exp $ ## Last modification: 8/3/00 by akp ## Originally written by Daniel Martin, Dept of Math, John Hopkins @@ -39,7 +39,8 @@ $close{'('} = ')'; my $binoper3 = '(?:\\^|\\*\\*)'; my $binoper2 = '[/*_,]'; -my $binoper1 = '(?:<>|<=|>=|[-+=><%!])'; +my $binoper1 = '(?:[-+%!])'; +my $binoper0 = '(?:<>|<=|>=|[=><])'; my $openparen = '[{(\\[]'; my $closeparen = '[})\\]]'; my $varname = '[A-Za-z](?:_[0-9]+)?'; @@ -64,7 +65,7 @@ my $trigfname = '(?:(?:a(?:rc)?)?(?:sin| my $otherfunc = '(?:exp|abs|logten|log|ln|sqrt|sgn|step|fact|int|lim|fun[a-zA-Z])'; my $funcname = '(?:' . $otherfunc . '|' . $trigfname . ')'; -my $tokenregexp = "(?:($binoper3)|($binoper2)|($binoper1)|($openparen)|" . +my $tokenregexp = "(?:($binoper3)|($binoper2)|($binoper1)|($binoper0)|($openparen)|" . "($closeparen)|($funcname)|($specialvalue)|($varname)|" . "($numberE)|($number))"; @@ -77,13 +78,14 @@ sub nexttoken { if (defined($1)) {return ['binop3', $1];} if (defined($2)) {return ['binop2', $2];} if (defined($3)) {return ['binop1', $3];} - if (defined($4)) {return ['openp', $4];} - if (defined($5)) {return ['closep', $5];} - if (defined($6)) {return ['func1', $6];} - if (defined($7)) {return ['special', $7];} - if (defined($8)) {return ['varname', $8];} - if (defined($9)) {return ['numberE', $9];} - if (defined($10)) {return ['number', $10];} + if (defined($4)) {return ['binop0', $4];} + if (defined($5)) {return ['openp', $5];} + if (defined($6)) {return ['closep', $6];} + if (defined($7)) {return ['func1', $7];} + if (defined($8)) {return ['special', $8];} + if (defined($9)) {return ['varname', $9];} + if (defined($10)) {return ['numberE',$10];} + if (defined($11)) {return ['number', $11];} } else { push @{$self->{posarray}}, [$p1, undef]; @@ -118,7 +120,7 @@ sub parse { local $_; while ($currenttok) { $_ = $currenttok->[0]; - /binop1/ && do { + /binop[01]/ && do { # check if we have a binary or unary operation here. if (defined(${$currentref})) { # binary - walk up the tree until we hit an open paren or the top @@ -126,16 +128,21 @@ sub parse { $currentref = pop @backtrace; } my $index = ((${$currentref}->[0] eq 'top')?1:3); - ${$currentref}->[$index] = ['binop1', $currenttok->[1], + ${$currentref}->[$index] = [$currenttok->[0], $currenttok->[1], ${$currentref}->[$index], undef]; push @backtrace, $currentref; push @backtrace, \${$currentref}->[$index]; $currentref = \${$currentref}->[$index]->[3]; - } else { + } elsif (/binop1/) { # unary ${$currentref} = ['unop1', $currenttok->[1], undef]; push @backtrace, $currentref; $currentref = \${$currentref}->[2]; + } else { + my ($mark) = pop(@{$self->{posarray}}); + my $position = 1+$mark->[0]; + return $self->error("Didn't expect " . $currenttok->[1] . + " at position $position" , $mark); } }; /binop2/ && do { @@ -482,9 +489,10 @@ sub tostring { # print STDERR Data::Dumper->Dump([@_]); my($self) = shift; my($type, @args) = @$self; + local $_; $_ = $type; - /binop1/ && do { + /binop[01]/ && do { my ($p1, $p2) = ('',''); if ($args[2]->[0] eq 'binop1') {($p1,$p2)=qw{ ( ) };} return ($args[1]->tostring() . $args[0] . $p1 . @@ -518,9 +526,6 @@ sub tostring { }; /special|varname|numberE?/ && return $args[0]; /closep/ && do { - my(%close) = %AlgParser::close; - - return ($args[0] . $args[1]->tostring() . $close{$args[0]}); }; @@ -529,9 +534,10 @@ sub tostring { sub tolatex { my($self) = shift; my($type, @args) = @$self; + local $_; $_ = $type; - /binop1/ && do { + /binop[01]/ && do { my ($p1, $p2) = ('',''); if ($args[2]->[0] eq 'binop1') {($p1,$p2)=qw{ \left( \right) };} my $cmd=$args[0]; @@ -551,17 +557,17 @@ sub tolatex { if ($args[0] eq '/'){ return('\frac{'.$lop.'}{'.$rop.'}'); } - elsif ($args[0] eq '*'){ - return($lop. '\cdot ' .$rop); + my $op = $args[0]; + if ($args[0] eq '*'){ + $op = '\cdot '; } - else{ - $lop = '\left('.$lop.'\right)' if ($args[1]->[0] =~ /binop1|numberE/); - $rop = '\left('.$rop.'\right)' if ($args[2]->[0] =~ /binop[12]|numberE|unop1/); - if ($args[0] =~ /implicit/) { - $args[0] = ($lop =~ m/[.0-9]$/ && $rop =~ m/^[-+.0-9]/) ? '\cdot ' : ' '; - } - return ($lop.$args[0].$rop); + $lop = '\left('.$lop.'\right)' if ($args[1]->[0] =~ /binop1|numberE/); + $rop = '\left('.$rop.'\right)' if ($args[2]->[0] =~ /binop[12]|numberE|unop1/); + if ($args[0] =~ /implicit/) { + $op = ($lop =~ m/[.0-9]$/ && $rop =~ m/^[-+.0-9]/) ? '\cdot ' : ' '; } + return ($lop.$op.$rop); + }; /binop3/ && do { my ($p1, $p2, $p3, $p4)=('','','',''); @@ -626,7 +632,7 @@ sub tolatex { /closep/ && do { my($backslash) = ''; if ($args[0] eq '{') {$backslash = '\\';} -#This is for editors to match: } +#This is for editors to match: } return ('\left' . $backslash . $args[0] . $args[1]->tolatex() . '\right' . $backslash . $close{$args[0]}); };