#!/usr/bin/perl # # Matthew Reeves # # This is a perl program to act as a scanner/interpreter for an imaginary language # use Modern::Perl; my $filename = $ARGV[0]; my $filestring; my $string; my $position = 0; my %table; open (FILE, $filename) or die "\nUnable to open file: $filename: $!\n"; while () { $filestring = $_; if ($filestring =~ /\/\/.+/) { $filestring = ""; } if ($filestring =~ /func.+/) { $filestring = ""; } if ($filestring =~ /endfunc/) { $filestring = ""; } if ($filestring ~~ "\n") { $filestring = ""; } if ($filestring =~ /^\s*\w+:/) { $filestring =~ s/:/:;/g; } if ($filestring =~ /^\s+.+/) { $filestring =~ s/^\s+//g; } if ($filestring =~ /\s+$/) { $filestring =~ s/\s+$/\n/g; } if ($filestring =~ /^if/i) { $filestring .= ";"; } $string .= $filestring; } close (FILE); $string =~ s/\n//g; my @stack = split(/;/, $string); my $len = @stack; while ($position < $len) { if ($stack[$position] ~~ /^write/i) { &write(); } elsif ($stack[$position] ~~ /^read/i) { &read(); } elsif ($stack[$position] ~~ /^\w+:/i) { $position++; } elsif ($stack[$position] ~~ /^to/i) { &goto(); } elsif ($stack[$position] ~~ /^if/i) { &if(); } elsif ($stack[$position] ~~ /^\w+/i) { &assign(); } else { $position++; } } sub write { my $tmp; if ($stack[$position] =~ /^write\s*\(\s*"(.*)?"\s*\)/i) { say "$1"; } elsif ($stack[$position] =~ /^write\s*\(\s*(\w*)?\s*\)/i) { say "$table{$1}"; } $position++; } sub read { my $tmp; if ($stack[$position] =~ /^read\s*\(\s*(\w*)?\s*\)/i) { $tmp = ; chomp $tmp; $table{$1} = $tmp; } $position++; } sub goto { my $tmp; my $count = 0; if ($stack[$position] =~ /^to\s+(.+)/i) { $tmp = $1.":"; while ($count < $len) { if ($stack[$count] ~~ $tmp) { $position = $count; $count = $len; } else { $count++; } } } else { $position++; } } sub if { my $compare; my $test1; my $test2; if ($stack[$position] =~ /^if\s*\(\s*(\w\w)\s*\(\s*(\w+|\d+)?\s*,\s*(\w+|\d+)?\s*\)/i) { if ($2 ~~ /^\d+$/) { $test1 = $2; } else { $test1 = $table{$2}; } ########################################### if ($3 ~~ /^\d+$/) { $test2 = $3; } else { $test2 = $table{$3}; } ########################################### if ($1 ~~ /gt/i) { if ($test1 > $test2) { $position++; } else { $position+=2; } } elsif ($1 ~~ /lt/i) { if ($test1 < $test2) { $position++; } else { $position+=2; } } elsif ($1 ~~ /eq/i) { if ($test1 == $test2) { $position++; } else { $position+=2; } } elsif ($1 ~~ /ge/i) { if ($test1 >= $test2) { $position++; } else { $position+=2; } } elsif ($1 ~~ /le/i) { if ($test1 <= $test2) { $position++; } else { $position+=2; } } elsif ($1 ~~ /ne/i) { if ($test1 != $test2) { $position++; } else { $position+=2; } } } elsif ($stack[$position] =~ /^if\s*\(\s*true\s*\)/i) { $position++; } else { $position+=2; } } sub assign { my $expr = $stack[$position]; $expr =~ s/\s*=\s*/ = /g; $expr =~ s/\s*\+\s*/ \+ /g; $expr =~ s/\s*-\s*/ - /g; $expr =~ s/\s*\*\s*/ \* /g; $expr =~ s/\s*\/\s*/ \/ /g; $expr =~ s/\s*%\s*/ % /g; $expr =~ s/\s*\(\s*/ \( /g; $expr =~ s/\s*\)\s*/ \) /g; $expr =~ s/\s+/ /g; $expr =~ s/;//g; $expr =~ s/\n//g; my @arr = split(/ /, $expr); my $count = 0; my $eva = ""; if ($expr =~ /\w+\s*=\s*\d+$/) { $table{$arr[0]} = $arr[2]; } else { foreach (@arr) { if ($count > 1) { if ($_ ~~ /(\d+|\+|\/|-|%|\*|\(|\))/) { $eva .= $_; } else { $eva .= $table{$_}; } } $count++; } $table{$arr[0]} = eval "$eva"; } $position++; }