[system] / trunk / pg / lib / Parser.pm Repository:
ViewVC logotype

Diff of /trunk/pg/lib/Parser.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2676 Revision 2678
1package Parser; 1package Parser;
2my $pkg = "Parser"; 2my $pkg = "Parser";
3
4use strict; 3use strict;
5#use Carp; 4
5#
6# Map class names to packages (added to Context, and
7# can be overriden to customize the parser)
8#
9our %class = {Formula => 'Parser::Formula'};
6 10
7################################################## 11##################################################
8# 12#
9# Parse a string and create a new Parser object 13# Parse a string and create a new Parser object
10# If the string is already a parsed object then copy the parse tree 14# If the string is already a parsed object then copy the parse tree
23 }, $class; 27 }, $class;
24 if (ref($string) =~ m/^(Parser|Value::Formula)/) { 28 if (ref($string) =~ m/^(Parser|Value::Formula)/) {
25 my $tree = $string; $tree = $tree->{tree} if exists $tree->{tree}; 29 my $tree = $string; $tree = $tree->{tree} if exists $tree->{tree};
26 $math->{tree} = $tree->copy($math); 30 $math->{tree} = $tree->copy($math);
27 } elsif (Value::isValue($string)) { 31 } elsif (Value::isValue($string)) {
28 $math->{tree} = Parser::Value->new($math,$string); 32 $math->{tree} = $math->{context}{parser}{Value}->new($math,$string);
29 } else { 33 } else {
30 $math->{string} = $string; 34 $math->{string} = $string;
31 $math->tokenize; 35 $math->tokenize;
32 $math->parse; 36 $math->parse;
33 } 37 }
214 } else { 218 } else {
215 $self->Precedence($op->{precedence}); 219 $self->Precedence($op->{precedence});
216 if ($self->state eq 'operand') { 220 if ($self->state eq 'operand') {
217 if ($op->{type} eq 'unary') { 221 if ($op->{type} eq 'unary') {
218 my $top = $self->pop; 222 my $top = $self->pop;
219 $self->pushOperand(Parser::UOP->new($self,$name,$top->{value},$ref)); 223 $self->pushOperand($context->{parser}{UOP}->new($self,$name,$top->{value},$ref));
220 } else { 224 } else {
221 $name = $context->{operators}{' '}{string} 225 $name = $context->{operators}{' '}{string}
222 if $name eq ' ' or $name eq $context->{operators}{' '}{space}; 226 if $name eq ' ' or $name eq $context->{operators}{' '}{space};
223 $self->pushOperator($name,$op->{precedence}); 227 $self->pushOperator($name,$op->{precedence});
224 } 228 }
292# Report the missing operation 296# Report the missing operation
293# 297#
294sub Close { 298sub Close {
295 my $self = shift; my $type = shift; 299 my $self = shift; my $type = shift;
296 my $ref = $self->{ref} = shift; 300 my $ref = $self->{ref} = shift;
301 my $parser = $self->{context}{parser};
297 my $parens = $self->{context}{parens}; 302 my $parens = $self->{context}{parens};
298 303
299 for ($self->state) { 304 for ($self->state) {
300 /open/ and do { 305 /open/ and do {
301 my $top = $self->pop; my $paren = $parens->{$top->{value}}; 306 my $top = $self->pop; my $paren = $parens->{$top->{value}};
302 if ($paren->{emptyOK} && $paren->{close} eq $type) { 307 if ($paren->{emptyOK} && $paren->{close} eq $type) {
303 $self->pushOperand(Parser::List->new($self,[],1,$paren)) 308 $self->pushOperand($parser->{List}->new($self,[],1,$paren))
304 } 309 }
305 elsif ($type eq 'start') {$self->Error("Missing close parenthesis for '$top->{value}'",$top->{ref})} 310 elsif ($type eq 'start') {$self->Error("Missing close parenthesis for '$top->{value}'",$top->{ref})}
306 elsif ($top->{value} eq 'start') {$self->Error("Extra close parenthesis '$type'",$ref)} 311 elsif ($top->{value} eq 'start') {$self->Error("Extra close parenthesis '$type'",$ref)}
307 else {$top->{ref}[3]=$ref->[3]; $self->Error("Empty parentheses",$top->{ref})} 312 else {$top->{ref}[3]=$ref->[3]; $self->Error("Empty parentheses",$top->{ref})}
308 last; 313 last;
315 if ($paren->{close} eq $type) { 320 if ($paren->{close} eq $type) {
316 my $top = $self->pop; 321 my $top = $self->pop;
317 if (!$paren->{removable} || ($top->{value}->type eq "Comma")) { 322 if (!$paren->{removable} || ($top->{value}->type eq "Comma")) {
318 $top = $top->{value}; 323 $top = $top->{value};
319 $top = {type => 'operand', value => 324 $top = {type => 'operand', value =>
320 Parser::List->new($self,[$top->makeList],$top->{isConstant},$paren, 325 $parser->{List}->new($self,[$top->makeList],$top->{isConstant},$paren,
321 ($top->type eq 'Comma') ? $top->entryType : $top->typeRef, 326 ($top->type eq 'Comma') ? $top->entryType : $top->typeRef,
322 ($type ne 'start') ? ($self->top->{value},$type) : () )}; 327 ($type ne 'start') ? ($self->top->{value},$type) : () )};
323 } 328 }
324 $self->pop; $self->push($top); 329 $self->pop; $self->push($top);
325 $self->CloseFn() if ($paren->{function} && $self->prev->{type} eq 'fn'); 330 $self->CloseFn() if ($paren->{function} && $self->prev->{type} eq 'fn');
326 } elsif ($paren->{formInterval} eq $type && $self->top->{value}->length == 2) { 331 } elsif ($paren->{formInterval} eq $type && $self->top->{value}->length == 2) {
327 my $top = $self->pop->{value}; my $open = $self->pop->{value}; 332 my $top = $self->pop->{value}; my $open = $self->pop->{value};
328 $self->pushOperand( 333 $self->pushOperand(
329 Parser::List->new($self,[$top->makeList],$top->{isConstant}, 334 $parser->{List}->new($self,[$top->makeList],$top->{isConstant},
330 $paren,$top->entryType,$open,$type)); 335 $paren,$top->entryType,$open,$type));
331 } else { 336 } else {
332 my $prev = $self->prev; 337 my $prev = $self->prev;
333 if ($type eq "start") {$self->Error("Missing close parenthesis for '$prev->{value}'",$prev->{ref})} 338 if ($type eq "start") {$self->Error("Missing close parenthesis for '$prev->{value}'",$prev->{ref})}
334 elsif ($prev->{value} eq "start") {$self->Error("Extra close parenthesis '$type'",$ref)} 339 elsif ($prev->{value} eq "start") {$self->Error("Extra close parenthesis '$type'",$ref)}
335 else {$self->Error("Mismatched parentheses: '$prev->{value}' and '$type'",$ref)} 340 else {$self->Error("Mismatched parentheses: '$prev->{value}' and '$type'",$ref)}
408 $self->push($fun); 413 $self->push($fun);
409 } else {$self->push($top,$op,$fun)} 414 } else {$self->push($top,$op,$fun)}
410 } else { 415 } else {
411 my $rop = $self->pop; my $op = $self->pop; my $lop = $self->pop; 416 my $rop = $self->pop; my $op = $self->pop; my $lop = $self->pop;
412 if ($op->{reverse}) {my $tmp = $rop; $rop = $lop; $lop = $tmp} 417 if ($op->{reverse}) {my $tmp = $rop; $rop = $lop; $lop = $tmp}
413 $self->pushOperand(Parser::BOP->new($self,$op->{name}, 418 $self->pushOperand($context->{parser}{BOP}->new($self,$op->{name},
414 $lop->{value},$rop->{value},$op->{ref}),$op->{reverse}); 419 $lop->{value},$rop->{value},$op->{ref}),$op->{reverse});
415 } 420 }
416 } else { 421 } else {
417 my $rop = $self->pop; my $op = $self->pop; 422 my $rop = $self->pop; my $op = $self->pop;
418 $self->pushOperand(Parser::UOP->new 423 $self->pushOperand($context->{parser}{UOP}->new
419 ($self,$op->{name},$rop->{value},$op->{ref}),$op->{reverse}); 424 ($self,$op->{name},$rop->{value},$op->{ref}),$op->{reverse});
420 } 425 }
421 last; 426 last;
422 }; 427 };
423 428
448 my $constant = $top->{isConstant}; 453 my $constant = $top->{isConstant};
449 if ($context->{parens}{$top->{open}}{function} && 454 if ($context->{parens}{$top->{open}}{function} &&
450 $context->{parens}{$top->{open}}{close} eq $top->{close} && 455 $context->{parens}{$top->{open}}{close} eq $top->{close} &&
451 !$context->{functions}{$fn->{name}}{vectorInput}) 456 !$context->{functions}{$fn->{name}}{vectorInput})
452 {$top = $top->coords} else {$top = [$top]} 457 {$top = $top->coords} else {$top = [$top]}
453 $self->pushOperand(Parser::Function->new 458 $self->pushOperand($context->{parser}{Function}->new
454 ($self,$fn->{name},$top,$constant,$fn->{ref})); 459 ($self,$fn->{name},$top,$constant,$fn->{ref}));
455} 460}
456 461
457################################################## 462##################################################
458# 463#
463# Save the number as an operand 468# Save the number as an operand
464# 469#
465sub Num { 470sub Num {
466 my $self = shift; 471 my $self = shift;
467 $self->ImplicitMult() if $self->state eq 'operand'; 472 $self->ImplicitMult() if $self->state eq 'operand';
468 my $num = Parser::Number->new($self,shift,$self->{ref}); 473 my $num = $self->{context}{parser}{Number}->new($self,shift,$self->{ref});
469 my $check = $self->{context}->flag('NumberCheck'); 474 my $check = $self->{context}->flag('NumberCheck');
470 &$check($num) if $check; 475 &$check($num) if $check;
471 $self->pushOperand($num); 476 $self->pushOperand($num);
472} 477}
473 478
477# 482#
478# Add an implicit multiplication, if needed 483# Add an implicit multiplication, if needed
479# Save the number as an operand 484# Save the number as an operand
480# 485#
481sub Const { 486sub Const {
482 my $self = shift; my $ref = $self->{ref}; 487 my $self = shift; my $ref = $self->{ref}; my $name = shift;
483 my $name = shift; my $const = $self->{context}{constants}{$name}; 488 my $const = $self->{context}{constants}{$name};
489 my $parser = $self->{context}{parser};
484 $self->ImplicitMult() if $self->state eq 'operand'; 490 $self->ImplicitMult() if $self->state eq 'operand';
485 if (defined($self->{context}{variables}{$name})) { 491 if (defined($self->{context}{variables}{$name})) {
486 $self->pushOperand(Parser::Variable->new($self,$name,$ref)); 492 $self->pushOperand($parser->{Variable}->new($self,$name,$ref));
487 } elsif ($const->{keepName}) { 493 } elsif ($const->{keepName}) {
488 $self->pushOperand(Parser::Constant->new($self,$name,$ref)); 494 $self->pushOperand($parser->{Constant}->new($self,$name,$ref));
489 } else { 495 } else {
490 $self->pushOperand(Parser::Value->new($self,[$const->{value}],$ref)); 496 $self->pushOperand($parser->{Value}->new($self,[$const->{value}],$ref));
491 } 497 }
492} 498}
493 499
494################################################## 500##################################################
495# 501#
499# Save the variable as an operand 505# Save the variable as an operand
500# 506#
501sub Var { 507sub Var {
502 my $self = shift; 508 my $self = shift;
503 $self->ImplicitMult() if $self->state eq 'operand'; 509 $self->ImplicitMult() if $self->state eq 'operand';
504 $self->pushOperand(Parser::Variable->new($self,shift,$self->{ref})); 510 $self->pushOperand($self->{context}{parser}{Variable}->new($self,shift,$self->{ref}));
505} 511}
506 512
507################################################## 513##################################################
508# 514#
509# Handle a function token 515# Handle a function token
525# Save the string object on the stack 531# Save the string object on the stack
526# 532#
527sub Str { 533sub Str {
528 my $self = shift; 534 my $self = shift;
529 $self->ImplicitMult() if $self->state eq 'operand'; 535 $self->ImplicitMult() if $self->state eq 'operand';
530 $self->pushOperand(Parser::String->new($self,shift,$self->{ref})); 536 $self->pushOperand($self->{context}{parser}{String}->new($self,shift,$self->{ref}));
531} 537}
532 538
533################################################## 539##################################################
534################################################## 540##################################################
535# 541#

Legend:
Removed from v.2676  
changed lines
  Added in v.2678

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9