# # This software is Copyright 2005 by Elsevier Inc. You may use it # under the terms of the license at http://perl.plover.com/hop/LICENSE.txt . # ### ### calculator ### ## Chapter 8 section 4.6 use Parser ':all'; use Lexer ':all'; my $input = allinput(\*STDIN); my $lexer = iterator_to_stream( make_lexer($input, ['TERMINATOR', qr/;\n*|\n+/ ], ['INT', qr/\d+/ ], ['PRINT', qr/\bprint\b/ ], ['IDENTIFIER', qr|[A-Za-z_]\w*| ], ['OP', qr#\*\*|[-=+*/()]# ], ['WHITESPACE', qr/\s+/, sub { "" } ], ) ); ## Chapter 8 section 4.6 my %VAR; my ($base, $expression, $factor, $program, $statement, $term); $Base = parser { $base->(@_) }; $Expression = parser { $expression->(@_) }; $Factor = parser { $factor->(@_) }; $Program = parser { $program->(@_) }; $Statement = parser { $statement->(@_) }; $Term = parser { $term->(@_) }; $program = concatenate(star($Statement), \&End_of_Input); $statement = alternate(T(concatenate(lookfor('PRINT'), $Expression, lookfor('TERMINATOR')), sub { print ">> $_[1]\n" }), T(concatenate(lookfor('IDENTIFIER'), lookfor(['OP', '=']), $Expression, lookfor('TERMINATOR') ), sub { $VAR{$_[0]} = $_[2] }), ); $expression = operator($Term, [lookfor(['OP', '+']), sub { $_[0] + $_[1] }], [lookfor(['OP', '-']), sub { $_[0] - $_[1] }]); $term = operator($Factor, [lookfor(['OP', '*']), sub { $_[0] * $_[1] }], [lookfor(['OP', '/']), sub { $_[0] / $_[1] }]); $factor = T(concatenate($Base, alternate(T(concatenate(lookfor(['OP', '**']), $Factor), sub { $_[1] }), T(\¬hing, sub { 1 }))), sub { $_[0] ** $_[1] }); $base = alternate(lookfor('INT'), lookfor('IDENTIFIER', sub { $VAR{$_[0][1]} || 0 }), T(concatenate(lookfor(['OP', '(']), $Expression, lookfor(['OP', ')'])), sub { $_[1] }) ); $program->($lexer);