Tuesday, May 19, 2009

Language interpreter

Its been some time since I was struck with this idea of an mini-language interpreter.
I started imagining it in the lines of an interpreter that could possibly understand scripts similar to the those written it the traditional bash shell scripts.
The work took some time. I choose perl to build the interpreter. The reason is obvious . The first reason was that I'd learned perl , and I wanted to use it somewhere. Second reason was that it was easier to do pattern matching in perl. So I started with what I call now the "Language Interpreter developed in perl". I'd initially scanned the web for tutorials that could help me on the project. I couldn't find any. I failed to find any documents on the web in a similar line. So after doing a fair amount of work and obtaining reasonable amount of results I thought I should post this on the web. So here it is...


#!/usr/bin/perl -w

while(<>)
{
chomp($_);
if($_) {match1($_);}
}

sub match1
{
$_=$_[0];

if(/^while\(([^\)]*)\){(.*)}$/)
{
#print "\nstat1 :",$1," ",$2,"\n";
$_=$1;
my $statements=$2;
if(/^([a-zA-Z][a-zA-Z0-9]*)([<>=!]*)([a-zA-Z0-9]+)$/)
{
my $lhs=symtabretrieve($1);
my $op=match($2);
my $rhs=match($3);
my $idl=$1;
my $idr=$3;
if($rhs==8) {$rhs=symtabretrieve($3);}
elsif($rhs==1) {$rhs=$3;}
if($op==2)
{
while($lhs<$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==3)
{
while($lhs>$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==4)
{
while($lhs>=$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==5)
{
while($lhs<=$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==6)
{
while($lhs==$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==7)
{
while($lhs!=$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}

}

return;

}


elsif(/^if\(([^\)]*)\){(.*)}$/)
{
#print "\nstat2 :",$1," ",$2,"\n";
$_=$1;
my $statements=$2;
if(/^([a-zA-Z][a-zA-Z0-9]*)([<>=!]*)([a-zA-Z0-9]+)$/)
{
my $lhs=symtabretrieve($1);
my $op=match($2);
my $rhs=match($3);
my $idl=$1;
my $idr=$3;
if($rhs==8) {$rhs=symtabretrieve($3);}
elsif($rhs==1) {$rhs=$3;}
if($op==2)
{
if($lhs<$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==3)
{
if($lhs>$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==4)
{
if($lhs>=$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==5)
{
if($lhs<=$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==6)
{
if($lhs==$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}
elsif($op==7)
{
if($lhs!=$rhs)
{
if($statements) {match1($statements);}
$lhs=symtabretrieve($idl);
$rhs=match($idr);
if($rhs==8) {$rhs=symtabretrieve($idr);}
elsif($rhs==1) {$rhs=$idr;}
}
}

}

return;
}


elsif(/^([a-zA-Z][a-zA-Z0-9]*)=([a-zA-Z0-9]+)$/)
{
#print "\nstat3 :",$1," ",$2,"\n";
syminsert($1,$2);
return;
}

elsif(/^([a-zA-Z][a-zA-Z0-9]*\[[0-9][0-9]*\])=([a-zA-Z0-9]+)$/)
{
#print "\nstat4 :",$1," ",$2,"\n";
syminsert($1,$2);
return;
}

elsif(/^([a-zA-Z][a-zA-Z0-9]*)=([a-zA-Z0-9]+)([p\+\-\*\/\%])([a-zA-Z0-9]+)$/)
{
#print "\nstat5 :",$1," ",$2,"\n";
if(match($2)==1) {$frstopd=$2;}
else {$frstopd=symtabretrieve($2);}
if(match($4)==1) {$scndop=$4;}
else {$scndop=symtabretrieve($4);}
$op=match($3);
if($op==9)
{
$val=$frstopd+$scndop;
syminsert($1,$val);
}
if($op==10)
{
$val=$frstopd-$scndop;
syminsert($1,$val);
}
if($op==11)
{
$val=$frstopd*$scndop;
syminsert($1,$val);
}
if($op==12)
{
$val=$frstopd/$scndop;
syminsert($1,$val);
}
if($op==13)
{
$val=$frstopd+$scndop;
syminsert($1,$val);
}
return;
}

elsif(/^echo \$([a-zA-Z0-9]+)\[\$?([a-zA-Z0-9][a-zA-Z0-9]*)\]$/)
{
#print "\nstat6 :",$1," ",$2,"\n";
$index=symtabretrieve($2);
if($index==undef)
{
$index=$1."[".$2."]";
print symtabretrieve($index);
}
else
{
$pr=$1."[".$index."]";
print symtabretrieve($pr);
}
print "\n";
return;
}

elsif(/^echo \$([a-zA-Z0-9]+)$/)
{
#print "\nstat7 :",$1,"\n";
print symtabretrieve($1);
print "\n";
return;
}

elsif(/^echo ([^;]*)$/)
{
#print "\nstat8 :",$1,"\n";
print $1;
print "\n";
return;
}

elsif(/^if/ || /^while/)
{
if(/^(.*});(.*)/)
{
my @temp=split(//,$1);
my $c=$2;
my $a="";
my $b="";
my $char='';
my $count=1;
while(@temp)
{
$char=shift(@temp);
$a.=$char;
if($char eq '{')
{
while($count)
{
$char=shift(@temp);
$a.=$char;
if($char eq '{') {$count++;}
elsif($char eq '}') {$count--;}
}
}
if(!$count) {$b=join('',@temp); @temp=();}
}
#print "\nstat9 :A:",$a," B:",$b," C:",$c,"\n";
if($a) {match1($a);}
if($b) {match1($b);}
if($c) {match1($c);}
}

return;
}

elsif(/^(.*?);(.*)$/)
{
#print "\nstat10 :A",$1," B:",$2,"\n";
my $a=$1; my $b=$2;
if($a) {match1($a);}
if($b) {match1($b);}
return;
}

}

sub match
{
$_=$_[0];
if(/^[0-9]+$/) {return 1;}
elsif(/^<$/) {return 2;}
elsif(/^>$/) {return 3;}
elsif(/^>=$/) {return 4;}
elsif(/^<=$/) {return 5;}
elsif(/^==$/) {return 6;}
elsif(/^!=$/) {return 7;}
elsif(/^[a-zA-Z0-9]+/) {return 8;}
elsif(/^\+/) {return 9;}
elsif(/^\-/) {return 10;}
elsif(/^\*/) {return 11;}
elsif(/^\//) {return 12;}
elsif(/^\%/) {return 13;}
else {return 0;}
}

sub syminsert
{
$symtab{$_[0]}=$_[1];
}

sub symtabretrieve
{
return $symtab{$_[0]};
}


The results I should say is only a miniature version of the project. And the code isn't fully shown. Your comments would be greatly appreciated.

Thanking you,
Layman

1 comment:

  1. This is obviously one great post. The information are very insightful and helpful. Thanks for sharing all of these.Legal Translation Services

    ReplyDelete