#!/usr/bin/perl -w
# @ Author: Loren Segal
# @ Date: March 2005
#
use strict; # strict programming style
###
## GLOBAL VARIABLES
###
my(%SYMTAB); # Global Symbol Table
my $NUMBER = qr/\d+(?:\.\d+)?/; # global number match
sub init_symtable($);
sub load_symtable();
sub lex($);
sub do_op($$);
sub main();
###
## START OF PROGRAM
###
main(); # call main()
## end of program
####
### SYMBOL TABLE FUNCTIONS
####
sub init_symtable($)
{
open(SYMTAB, $_[0]) or die("% Error: could not open file '$_[0]': $!\n");
}
sub load_symtable()
{
local $_;
for (<SYMTAB>) { $SYMTAB{$1} = $2 if (m/^\s*(\w+):.*\svalue=($NUMBER)/); }
close(SYMTAB);
}
###
## MATH PARSING FUNCTIONS
###
## Function: lex(EXPR)
#
## Description: Does order of operations on the following EXPR, expanding each set of brackets
# from inside out.
#
sub lex($) {
local ($_) = @_;
my $name;
# Expand all identifiers
for $name (sort keys %SYMTAB) { s/\b$name\b/$SYMTAB{$name}/g; }
while (m/\(([^(]+)\)/) {
my $ans = $1;
$ans = do_op($ans, '^'); # Do exponents (not required)
$ans = do_op($ans, '*'); # Do multiplication
$ans = do_op($ans, '/'); # Do division
$ans = do_op($ans, '%'); # Do modular division (not required)
$ans = do_op($ans, '+'); # Do addition
$ans = do_op($ans, '-'); # Do subtraction
s/\([^(]+\)/$ans/; # Expand the bracket into the answer
}
return "Syntax error." if (!m/^$NUMBER$/);
return $_;
}
## Function: do_op(EXPR, OPERAND)
#
## Description: Searches through EXPR for a NUMBER followed by OPERAND followed by NUMBER and expands
# it into its mathematical value. Continues until no matches are found for the OPERAND.
#
sub do_op($$) {
local $_ = shift(@_);
my($op) = @_;
my $re = qr/\b($NUMBER)\Q$op\E($NUMBER)\b/;
while (m/$re/) {
my $ans = eval("$1 $op $2");
s/$re/$ans/;
}
return $_;
}
## Function: main()
#
## Description: main program function
#
sub main() {
init_symtable("symbolfile.txt"); # initiate symbol table, hardcoded location
load_symtable(); # load keyval pairs into table
local $_ = <STDIN>; # get mathematical input
s/\s*//g; # remove ALL spaces
s/(.+)/($1)/; # wrap the line in brackets ()
$_ = lex($_); # call the math function
print "Answer: $_\n"; # print the answer
}
Powered by
GeSHi Syntax Highlighting software.
Author of all (other) material unless otherwise specified:
Loren Segal. Copyright 2005.