import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
public class hw3 {
public static void hw4(String input, String output) throws IOException{
PrintStream myconsole=new PrintStream(new File(output));
System.setOut(myconsole);
BufferedReader in = new BufferedReader(new FileReader(input));
ArrayList stack = new ArrayList();
HashMap hm = new HashMap();
String line = in.readLine();
while(line!=null){
if(line.equals(“let”)) {
stack.add(0,parseLet(in,hm,myconsole));
}
else if(Character.isLetter(line.charAt(0))){
stack = parsePrimitive(line, stack, hm, myconsole);
}
else if(line.charAt(0)==’:’){
stack = parseBooleanOrError(line, stack, hm);
}
else{
myconsole.println(“Error command!”);
}
line = in.readLine();
}
in.close();
}
public static Object parseLet(BufferedReader in, HashMap hm_parent, PrintStream myconsole) throws IOException {
ArrayList stack_let = new ArrayList();
HashMap hm_let = new HashMap(hm_parent);
String line = in.readLine();
while(!line.equals(“end”)){
if(line.equals(“let”)) {
stack_let.add(0,parseLet(in,hm_let,myconsole));
}
else if(Character.isLetter(line.charAt(0))){
stack_let = parsePrimitive(line, stack_let, hm_let, myconsole);
}
else if(line.charAt(0)==’:’){
stack_let = parseBooleanOrError(line, stack_let, hm_let);
}
else{
myconsole.println(“Error command!”);
}
line = in.readLine();
}
return stack_let.get(0);
}
public static ArrayList parseBooleanOrError(String line, ArrayList stack, HashMap hm) {
if (line.startsWith(“:e”)){
stack.add(0, “:error:”);
}
else if (line.startsWith(“:t”)){
stack.add(0, “:true:”);
}
else if (line.startsWith(“:f”)){
stack.add(0, “:false:”);
}
return stack;
}
public static ArrayList doMul(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
stack.remove(0);
stack.remove(0);
Integer newTop = x*y;
stack.add(0, newTop.toString());
}
return stack;
}
public static ArrayList doSub(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
stack.remove(0);
stack.remove(0);
Integer newTop = x-y;
stack.add(0, newTop.toString());
}
return stack;
}
public static ArrayList doAdd(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“(.*)[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“(.*)[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
stack.remove(0);
stack.remove(0);
Integer newTop = x+y;
stack.add(0, newTop.toString());
}
return stack;
}
public static ArrayList parsePrimitive(String line, ArrayList stack, HashMap hm, PrintStream myconsole){
if (line.startsWith(“add”)){
stack = doAdd(stack,hm);
}
else if (line.startsWith(“sub”)){
stack = doSub(stack,hm);
}
else if (line.startsWith(“mul”)){
stack = doMul(stack,hm);
}
else if (line.startsWith(“div”)){
stack = doDiv(stack,hm);
}
else if (line.startsWith(“rem”)){
stack = doRem(stack, hm);
}
else if (line.startsWith(“pop”)){
stack = doPop(stack);
}
else if (line.startsWith(“push”)){
stack = doPush(stack, line);
}
else if (line.startsWith(“swap”)){
stack = doSwap(stack);
}
else if (line.startsWith(“neg”)){
stack = doNeg(stack,hm);
}
else if (line.startsWith(“quit”)){
doQuit(stack, myconsole);
}
else if (line.startsWith(“if”)) {
doIf(stack,hm);
}
else if (line.startsWith(“not”)) {
doNot(stack,hm);
}
else if (line.startsWith(“and”)) {
doAnd(stack,hm);
}
else if (line.startsWith(“or”)) {
doOr(stack,hm);
}
else if (line.startsWith(“equal”)) {
doEqual(stack,hm);
}
else if (line.startsWith(“lessThan”)) {
doLessThan(stack,hm);
}
else if (line.startsWith(“bind”)) {
doBind(stack,hm);
}
return stack;
}
public static void doQuit(ArrayList stack, PrintStream myconsole) {
for (int i = 0; i < stack.size(); i++){
String s = (String) stack.get(i);
myconsole.println(s.replace(“\””,””));
}
myconsole.close();
}
public static ArrayList doNeg(ArrayList stack, HashMap hm) {
if (stack.isEmpty()){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
int x;
String s0 = (String) stack.get(0);
if(s0.matches(“(.*)[0-9]+”)) x = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s0_1);
}
Integer newTop = -1*x;
stack.remove(0);
stack.add(0, newTop.toString());
}
return stack;
}
private static ArrayList doSwap(ArrayList stack) {
if (stack.size() < 2){
stack.add(0, “:error:”);
}
else{
String x = (String) stack.get(1);
String y = (String) stack.get(0);
stack.remove(0);
stack.remove(0);
stack.add(0, y);
stack.add(0, x);
}
return stack;
}
public static ArrayList doPush(ArrayList stack, String line) {
String getNum = line.substring(5);
if (getNum.charAt(0) == ‘-‘){
if (getNum.substring(1).equals(“0”)){
stack.add(“0”);
}
else if (getNum.substring(1).matches(“[0-9]+”)){
stack.add(0, getNum);
}
else{
stack.add(0, “:error:”);
}
}
else if (getNum.matches(“[0-9]+”)){
stack.add(0, getNum);
}
else if (getNum.matches(“^[a-zA-Z].*”)){
stack.add(0, getNum);
}
else if (getNum.matches(“^\”.+\”$”)){
stack.add(0, getNum);
}
else{
stack.add(0, “:error:”);
}
return stack;
}
public static ArrayList doPop(ArrayList stack) {
if (stack.size() < 1){
stack.add(0, “:error:”);
}
else{
stack.remove(0);
}
return stack;
}
public static ArrayList doRem(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
if (y == 0){
stack.add(0, “:error:”);
}
else{
stack.remove(0);
stack.remove(0);
Integer newTop = x%y;
stack.add(0, newTop.toString());
}
}
return stack;
}
public static ArrayList doDiv(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
if (y == 0){
stack.add(0, “:error:”);
}
else{
stack.remove(0);
stack.remove(0);
Integer newTop = x/y;
stack.add(0, newTop.toString());
}
}
return stack;
}
public static ArrayList doIf(ArrayList stack, HashMap hm) {
if (stack.size()<3){
stack.add(0, “:error:”);
}
else {
String s2 = (String) stack.get(2);
if(!s2.equals(“:true:”) && !s2.equals(“:false:”)) s2 = (String) hm.get(s2);
if (s2 != null && s2.equals(“:true:”)) {
stack.remove(2);
stack.remove(1);
}
else if (s2 != null && s2.equals(“:false:”)) {
stack.remove(2);
stack.remove(0);
}
else{
stack.add(0, “:error:”);
}
}
return stack;
}
public static ArrayList doNot(ArrayList stack, HashMap hm) {
if (stack.size()<1){
stack.add(0, “:error:”);
}
else {
String s0 = (String) stack.get(0);
if(!s0.equals(“:true:”) && !s0.equals(“:false:”)) s0 = (String) hm.get(s0);
if(s0 == null){
stack.add(0, “:error:”);
}
else if (s0.equals(“:true:”)) {
stack.remove(0);
stack.add(0, “:false:”);
}
else if (s0.equals(“:false:”)) {
stack.remove(0);
stack.add(0, “:true:”);
}
else{
stack.add(0, “:error:”);
}
}
return stack;
}
public static ArrayList doAnd(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else {
String s0 = (String) stack.get(0);
if(!s0.equals(“:true:”) && !s0.equals(“:false:”)) s0 = (String) hm.get(s0);
String s1 = (String) stack.get(1);
if(!s1.equals(“:true:”) && !s1.equals(“:false:”)) s1 = (String) hm.get(s1);
if(s0 == null || s1 == null) {
stack.add(0, “:error:”);
}
else if (s0.equals(“:false:”) && s1.equals(“:false:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:false:”);
}
else if (s0.equals(“:false:”) && s1.equals(“:true:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:false:”);
}
else if (s0.equals(“:true:”) && s1.equals(“:false:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:false:”);
}
else if (s0.equals(“:true:”) && s1.equals(“:true:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:true:”);
}
else{
stack.add(0, “:error:”);
}
}
return stack;
}
public static ArrayList doOr(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else {
String s0 = (String) stack.get(0);
if(!s0.equals(“:true:”) && !s0.equals(“:false:”)) s0 = (String) hm.get(s0);
String s1 = (String) stack.get(1);
if(!s1.equals(“:true:”) && !s1.equals(“:false:”)) s1 = (String) hm.get(s1);
if(s0 == null || s1 == null) {
stack.add(0, “:error:”);
}
else if (s0.equals(“:false:”) && s1.equals(“:false:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:false:”);
}
else if (s0.equals(“:false:”) && s1.equals(“:true:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:true:”);
}
else if (s0.equals(“:true:”) && s1.equals(“:false:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:true:”);
}
else if (s0.equals(“:true:”) && s1.equals(“:true:”)) {
stack.remove(0);
stack.remove(0);
stack.add(0, “:true:”);
}
else{
stack.add(0, “:error:”);
}
}
return stack;
}
public static ArrayList doEqual(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
stack.remove(0);
stack.remove(0);
if(x == y) stack.add(0, “:true:”);
else stack.add(0, “:false:”);
}
return stack;
}
public static ArrayList doLessThan(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else if (((String) stack.get(0)).charAt(0) == ‘:’ || ((String) stack.get(1)).charAt(0) == ‘:’){
stack.add(0, “:error:”);
}
else{
String s1 = (String) stack.get(1);
String s0 = (String) stack.get(0);
int x,y;
if(s1.matches(“[0-9]+”)) x = Integer.parseInt(s1);
else {
String s1_1 = (String) hm.get(s1);
if(s1_1 == null || !s1_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
x = Integer.parseInt(s1_1);
}
if(s0.matches(“[0-9]+”)) y = Integer.parseInt(s0);
else {
String s0_1 = (String) hm.get(s0);
if(s0_1 == null || !s0_1.matches(“[0-9]+”)) {
stack.add(0, “:error:”);
return stack;
}
y = Integer.parseInt(s0_1);
}
stack.remove(0);
stack.remove(0);
if(x < y) stack.add(0, “:true:”);
else stack.add(0, “:false:”);
}
return stack;
}
public static ArrayList doBind(ArrayList stack, HashMap hm) {
if (stack.size()<2){
stack.add(0, “:error:”);
}
else {
String s0 = (String) stack.get(0);
String s1 = (String) stack.get(1);
if(s1.matches(“^[a-zA-Z].*”) && !s0.equals(“:error:”)) {
stack.remove(0);
stack.remove(0);
Object o = hm.get(s0);
if(o!=null) hm.put(s1,o);
else hm.put(s1,s0);
stack.add(0, “:unit:”);
}
else {
stack.add(0, “:error:”);
}
}
return stack;
}
}
import re
fInput = 0
def hw3(input, output):
global fInput
fInput = open(input,’r’)
f = open(output,’w’)
stack = []
hm = {}
for line in fileRead():
if line.startswith(‘let’):
stack.insert(0,parseLet(fInput,hm,f))
elif line[0].isalpha():
parsePrimitive(line, stack, hm, f)
elif line[0] == ‘:’:
parseBooleanOrError(line, stack, hm)
fInput.close()
def fileRead():
for line in fInput:
yield line
def parseLet(input,hm_parent,f):
global fInput
stack_let = []
hm_let = {}
for line in fileRead():
if line.startswith(‘end’):
return stack_let[0]
elif line[0] == ‘let’:
stack.insert(0,parseLet(fInput,hm_let,f))
elif line[0].isalpha():
parsePrimitive(line, stack_let, hm_let, f)
elif line[0] == ‘:’:
parseBooleanOrError(line, stack_let, hm_let)
def parsePrimitive(line, stack, hm, f):
if line.startswith(‘add’):
doAdd(stack, hm)
elif line.startswith(‘sub’):
doSub(stack, hm)
elif line.startswith(‘mul’):
doMul(stack, hm)
elif line.startswith(‘div’):
doDiv(stack, hm)
elif line.startswith(‘rem’):
doRem(stack, hm)
elif line.startswith(‘pop’):
doPop(stack)
elif line.startswith(‘push’):
doPush(stack, line)
elif line.startswith(‘swap’):
doSwap(stack)
elif line.startswith(‘neg’):
doNeg(stack, hm)
elif line.startswith(‘quit’):
doQuit(stack, f)
elif line.startswith(‘if’):
doIf(stack, hm)
elif line.startswith(‘not’):
doNot(stack, hm)
elif line.startswith(‘and’):
doAnd(stack, hm)
elif line.startswith(‘or’):
doOr(stack, hm)
elif line.startswith(‘equal’):
doEqual(stack, hm)
elif line.startswith(‘lessThan’):
doLessThan(stack, hm)
elif line.startswith(‘bind’):
doBind(stack, hm)
def doAdd(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
stack.pop(0)
stack.pop(0)
newTop = x+y
return stack.insert(0, str(newTop))
else:
return stack.insert(0, ‘:error:’)
def doSub(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
stack.pop(0)
stack.pop(0)
newTop = x-y
return stack.insert(0, str(newTop))
else:
return stack.insert(0, ‘:error:’)
def doMul(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
stack.pop(0)
stack.pop(0)
newTop = x*y
return stack.insert(0, str(newTop))
else:
return stack.insert(0, ‘:error:’)
def doDiv(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
if y == 0:
return stack.insert(0, ‘:error:’)
stack.pop(0)
stack.pop(0)
newTop = x*y
return stack.insert(0, str(newTop))
else:
return stack.insert(0, ‘:error:’)
def doRem(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
if y == 0:
return stack.insert(0, ‘:error:’)
stack.pop(0)
stack.pop(0)
newTop = x%y
return stack.insert(0, str(newTop))
else:
return stack.insert(0, ‘:error:’)
def doPop(stack):
if len(stack) < 1:
return stack.insert(0, ‘:error:’)
else:
return stack.pop(0)
def doPush(stack, line):
getList = line.split()
if getList[1][0] == ‘-‘:
if getList[1][1:] == ‘0’:
return stack.insert(0,’0′)
elif getList[1][1:].isdigit():
return stack.insert(0, getList[1])
else:
return stack.insert(0, ‘:error:’)
elif getList[1].isdigit():
return stack.insert(0, getList[1])
elif re.match(‘^[a-zA-Z].*’,getList[1],0):
return stack.insert(0, getList[1])
elif re.match(‘^”.+”$’,getList[1],0):
return stack.insert(0, getList[1])
else:
return stack.insert(0, ‘:error:’)
def doSwap(stack):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
else:
x = stack[1]
y = stack[0]
stack.pop(0)
stack.pop(0)
stack.insert(0, y)
return stack.insert(0, x)
def doNeg(stack, hm):
if len(stack) < 1:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if s0.isdigit:
x = int(s0)
stack.pop(0)
newTop = -1*x
return stack.insert(0, str(newTop))
else:
return stack.insert(0, ‘:error:’)
def doQuit(stack, f):
for ele in stack:
f.write(ele.strip(‘”‘) + ‘\n’)
f.close()
def parseBooleanOrError(line, stack, hm):
if line[1] == ‘e’:
return stack.insert(0,’:error:’)
elif line[1] == ‘t’:
return stack.insert(0,’:true:’)
else:
return stack.insert(0,’:false:’)
def doIf(stack, hm):
if len(stack) < 3:
return stack.insert(0, ‘:error:’)
else:
s2 = str(stack[2])
if s2 != ‘:true:’ and s2 != ‘:false:’:
s2 = str(hm.get(s2,s2))
if s2 == ‘:true:’:
stack.pop(2)
stack.pop(1)
return stack
elif s2 == ‘:false:’:
stack.pop(2)
stack.pop(0)
return stack
else:
return stack.insert(0,’:error:’)
def doNot(stack, hm):
if len(stack) < 1:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
if s0 != ‘:true:’ and s0 != ‘:false:’:
s0 = str(hm.get(s0,s0))
if s0 == ‘:true:’:
stack.pop(0)
stack.insert(0,’:false:’)
return stack
elif s0 == ‘:false:’:
stack.pop(0)
stack.insert(0,’:true:’)
return stack
else:
return stack.insert(0,’:error:’)
def doAnd(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if s0 != ‘:true:’ and s0 != ‘:false:’:
s0 = str(hm.get(s0,s0))
if s1 != ‘:true:’ and s1 != ‘:false:’:
s1 = str(hm.get(s1,s1))
if s0 == ‘:false:’ and s1 == ‘:false:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:false:’)
return stack
elif s0 == ‘:false:’ and s1 == ‘:true:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:false:’)
return stack
elif s0 == ‘:true:’ and s1 == ‘:false:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:false:’)
return stack
elif s0 == ‘:true:’ and s1 == ‘:true:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:true:’)
return stack
else:
return stack.insert(0,’:error:’)
def doOr(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if s0 != ‘:true:’ and s0 != ‘:false:’:
s0 = str(hm.get(s0,s0))
if s1 != ‘:true:’ and s1 != ‘:false:’:
s1 = str(hm.get(s1,s1))
if s0 == ‘:false:’ and s1 == ‘:false:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:false:’)
return stack
elif s0 == ‘:false:’ and s1 == ‘:true:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:true:’)
return stack
elif s0 == ‘:true:’ and s1 == ‘:false:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:true:’)
return stack
elif s0 == ‘:true:’ and s1 == ‘:true:’:
stack.pop(0)
stack.pop(0)
stack.insert(0,’:true:’)
return stack
else:
return stack.insert(0,’:error:’)
def doEqual(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
stack.pop(0)
stack.pop(0)
if x==y:
return stack.insert(0, ‘:true:’)
else:
return stack.insert(0, ‘:false:’)
else:
return stack.insert(0, ‘:error:’)
def doLessThan(stack, hm):
if len(stack) < 2:
return stack.insert(0, ‘:error:’)
elif stack[0][0] == ‘:’ or stack[1][0] == ‘:’:
return stack.insert(0, ‘:error:’)
else:
s0 = str(stack[0])
s1 = str(stack[1])
if re.match(‘^[a-zA-Z].*’,s0,0):
s0 = str(hm.get(s0,s0))
if re.match(‘^[a-zA-Z].*’,s1,0):
s1 = str(hm.get(s1,s1))
if s0.isdigit and s1.isdigit:
y = int(s0)
x = int(s1)
stack.pop(0)
stack.pop(0)
if x<y:
return stack.insert(0, ‘:true:’)
else:
return stack.insert(0, ‘:false:’)
else:
return stack.insert(0, ‘:error:’)
def doBind(stack, hm):
if len(stack) < 2:
return stack.insert(0,’:error:’)
else:
s0 = stack[0]
s1 = stack[1]
if re.match(‘^[a-zA-Z].*’,stack[1],0) and stack[0] != ‘:error:’:
stack.pop(0)
stack.pop(0)
s0 = str(hm.get(s0,s0))
hm[s1] = s0
return stack.insert(0,’:unit:’)
else:
return stack.insert(0,’:error:’)
(* CSE305 Spring 2016
* A possible solution to HW2, expressed in Standard ML
* Author: Carl Alphonce
* Modified: Lu Meng
*)
(****************************************************************************
TYPE DEFINITIONS
****************************************************************************)
(* The type of expressions and special forms *)
datatype exp =
Boolean of bool
| Number of int
| String of string
| Name of string
| Error | Quit | Add | Sub | Mul | Div | Rem | Pop | Swap | Neg |
And | Or | Not | Bind | Equals | LessThan | If | Let | End | Unit;
(****************************************************************************
UTILITY FUNCTIONS
****************************************************************************)
(* Utility function to build a textual form of an expression
or special form, used for printing.
*)
fun expression2string(Boolean(true)) = “:true:”
| expression2string(Boolean(false)) = “:false:”
| expression2string(String(s)) = s
| expression2string(Number(X)) = if (X<0) then “-“^Int.toString(~X) else Int.toString(X)
| expression2string(Error) = “:error:”
| expression2string(Unit) = “:unit:”
| expression2string(Name(x)) = x
| expression2string(Let) = “let”
| expression2string(End) = “end”
| expression2string(_) = “?? should not happen ??”
;
(* Computes quotient according to rules of the language *)
fun quotient(a2,a1) =
if (a1<0)
then if (a2 div a1) * a1 > a2 then (a2 div a1)+1 else (a2 div a1)
else (a2 div a1);
(* Computes remainder according to rules of the language *)
fun remainder(a2,a1) = a2 – a1 * quotient(a2,a1);
(****************************************************************************
MAIN EVALUATOR FUNCTIONS
****************************************************************************)
(* Applies a primitive function to its two arguments *)
fun
(* 0-ARY OPERATORS *)
apply(_,[]) = (Error,[])
(* UNARY OPERATORS *)
| apply(Neg,Number(a)::rest) = (Number(~a),rest)
| apply(Not,Boolean(a) :: rest) = (Boolean(not a), rest)
| apply(_,[x]) = (Error,[x])
(* BINARY OPERATORS *)
| apply(Add,Number(a1)::Number(a2)::rest) = (Number(a2+a1),rest)
| apply(Sub,Number(a1)::Number(a2)::rest) = (Number(a2-a1),rest)
| apply(Mul,Number(a1)::Number(a2)::rest) = (Number(a2*a1),rest)
| apply(Div,Number(a1)::Number(a2)::rest) = (if a1 = 0 then (Error,Number(a1)::Number(a2)::rest) else (Number(quotient(a2,a1)),rest))
| apply(Rem,Number(a1)::Number(a2)::rest) = (if a1 = 0 then (Error,Number(a1)::Number(a2)::rest) else (Number(remainder(a2,a1)),rest))
| apply(Equals, Number(a1) :: Number(a2) :: rest) = (Boolean(a2 = a1), rest)
| apply(LessThan, Number(a1) :: Number(a2) :: rest) = (Boolean(a2 < a1), rest)
| apply(And, Boolean(a1) :: Boolean(a2) :: rest) = (Boolean(a2 andalso a1), rest)
| apply(Or, Boolean(a1) :: Boolean(a2) :: rest) = (Boolean(a2 orelse a1), rest)
(* TERNARY OPERATORS *)
| apply(If, a1 :: a2 :: Boolean(true) :: rest) = (a1, rest)
| apply(If, a1 :: a2 :: Boolean(false) :: rest) = (a2, rest)
(*Anything else results in an error *)
| apply(_,stack) = (Error,stack)
;
(* Functions to look up name in the list of environments *)
fun lookup2(Name(x),[]) = NONE
| lookup2(Name(x), (Name(y),value)::bindings) =
if (x=y) then SOME(value)
else lookup2(Name(x),bindings)
| lookup2(_,_) = SOME(Error);
fun lookup(Name(x),[]) = Name(x)
| lookup(Name(x),e::es) = (
case (lookup2(Name(x),e)) of
NONE => lookup(Name(x),es)
| SOME(v) => v )
| lookup(_,_) = Error;
(* Function to check if a name is bound *)
fun isBound(Name(x),[]) = NONE
| isBound(Name(x),e::es) = (
case (lookup2(Name(x),e)) of
NONE => isBound(Name(x),es)
| SOME(v) => SOME(v))
| isBound(_,_) = SOME(Error);
fun bind(Error::Name(n)::rest, e :: es) = (Error::Name(n)::rest, e :: es)
| bind(Unit::Name(n)::rest, e::es) = (Unit::rest,((Name(n),Unit)::e)::es)
| bind(String(s) :: Name(n) :: rest, e::es) = (Unit::rest, ((Name(n),String(s))::e)::es)
| bind(Number(x) :: Name(n) :: rest, e::es) = (Unit::rest, ((Name(n),Number(x))::e)::es)
| bind(Boolean(s) :: Name(n) :: rest, e::es) = (Unit::rest, ((Name(n),Boolean(s))::e)::es)
| bind(Name(value) ::Name(n)::rest, e::es) = (
case (isBound(Name(value),e::es)) of
NONE => (Error:: Name(value) :: Name(n) ::rest, e::es)
| SOME(c) => (Unit::rest, ((Name(n),c)::e)::es)
)
| bind(value::Name(n)::rest, e::es) = (
case (isBound(value,e::es)) of
NONE => (Unit::rest, ((Name(n),value)::e)::es)
| SOME(c) => (Unit::rest,((Name(n),c)::e)::es) )
| bind(stack,envs) = (Error::stack, envs);
| bind(value ::Name(n)::rest, e::es) = (
case (isBound(Name(n),e::es)) of
NONE => (Unit::rest, ((Name(n),value)::e)::es)
| SOME(c) => (Unit::rest, ((Name(n),c)::e)::es)
)
| bind(stack,envs) = (Error::stack, envs);
fun doPop(Let :: rest) = rest
| doPop(a :: b) = doPop(b)
| doPop([]) = [] ;
fun doLet(stack, envs) = ( Let :: stack,envs);
fun doEnd(a :: rest, envs) = ( a :: doPop(rest),envs) ;
(* stack operations *)
fun stackOps(Pop, x::stack) = stack
| stackOps(Swap, x::y::stack) = y::x::stack
| stackOps(_,stack) = Error::stack
;
(* Evaluates an expression *)
fun eval(Boolean(x), stack, env) = (Boolean(x)::stack , env)
| eval(Number(x), stack , env) = (Number(x)::stack , env)
| eval(Name(x), stack, env) = (lookup(Name(x),env)::stack, env)
| eval(Bind, stack, env) = bind(stack, env)
| eval(Let,stack,env) = doLet(stack,env)
| eval(End,stack,env) = doEnd(stack,env)
| eval(Quit, stack, env) = (Quit::stack , env)
| eval(Pop, x::stack, env) = (stack , env)
| eval(String(x), stack, env) = (String(x)::stack,env)
| eval(Swap, x::y::stack , env) = (y::x::stack, env)
| eval(Error, stack , env) = (Error::stack,env)
| eval(Unit,stack , env) = (Unit::stack, env)
| eval(expr, stack , env) = let
val (v,s) = apply(expr, stack)
in
(v::s , env)
end;
(* Functions to parse a number *)
fun parseNumber(x,inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (Char.isDigit(ch)) then parseNumber(x*10+(ord(ch)-ord(#”0″)),inStr)
else if (Char.isSpace(ch)) then SOME(Number(x))
else SOME(Error)
;
fun parseNegativeNumber(inStr) =
case ( parseNumber(0,inStr) ) of
NONE => SOME(Error)
| SOME(Number(num)) => SOME(Number(~1 * num))
| SOME(_) => SOME(Error)
;
(* Function to parse a boolean *)
fun parseBoolean(x, inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (Char.isAlpha(ch) orelse ch = #”:”) then parseBoolean(x^Char.toString(ch),inStr)
else if (Char.isSpace(ch))
then if (x = “:true:”) then SOME(Boolean(true))
else if (x = “:false:”) then SOME(Boolean(false))
else SOME(Error)
else SOME(Error);
(* Function to parse an error *)
fun parseError(x, inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (Char.isAlpha(ch) orelse ch = #”:”) then parseError(x^Char.toString(ch),inStr)
else if (Char.isSpace(ch))
then if (x = “:error:”) then SOME(Error)
else SOME(Error)
else SOME(Error);
(***** EDITED TO HERE ********************************************************************)
(* Function to parse a boolean or error *)
fun parseString(x, inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (ch = #”\””) then SOME(String(x))
else parseString(x^Char.toString(ch),inStr)
fun parseBooleanOrError(x, inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (ch = #”e”) then parseError(x^Char.toString(ch),inStr)
else if (ch = #”t” orelse ch = #”f”) then parseBoolean(x^Char.toString(ch),inStr)
else SOME(Error);
(* Function to parse a primitive *)
fun parsePrimitive(x, inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (Char.isAlpha(ch) orelse Char.isDigit(ch)) then parsePrimitive(x^Char.toString(ch),inStr)
else if (ch = #”\n”)
then if (x = “add”) then SOME(Add)
else if (x = “sub”) then SOME(Sub)
else if (x = “mul”) then SOME(Mul)
else if (x = “div”) then SOME(Div)
else if (x = “rem”) then SOME(Rem)
else if (x = “pop”) then SOME(Pop)
else if (x = “swap”) then SOME(Swap)
else if (x = “neg”) then SOME(Neg)
else if (x = “and”) then SOME(And)
else if (x = “or”) then SOME(Or)
else if (x = “not”) then SOME(Not)
else if (x = “equal”) then SOME(Equals)
else if (x = “lessThan”) then SOME(LessThan)
else if (x = “if”) then SOME(If)
else if (x = “bind”) then SOME(Bind)
else if (x = “quit”) then SOME(Quit)
else if (x = “let”) then SOME(Let)
else if(x = “end”) then SOME(End)
else SOME(Name(x))
else SOME(Error);
fun parsePush(inStr) =
case (TextIO.input1(inStr)) of
NONE => SOME(Error)
| SOME(ch) =>
if (Char.isAlpha(ch)) then parsePush(inStr)
else if (Char.isSpace(ch))
then if (TextIO.input1(inStr) = SOME(c)) then
(if c = #”-“) then parseNegativeNumber(inStr)
else parseNumber(ord(TextIO.input1(inStr))-ord(#”0″),inStr))
else SOME(Error);
(* A recursive helper function for the parse function, which reads
a character from the input stream and determines what more
specific parsing function to call.
*)
fun parseHelper(NONE, inStr) = NONE
| parseHelper(SOME(ch), inStr) =
let
val line = Option.valOf (TextIO.inputLine inStr)
val second = String.sub (line, 0)
val inStr1 = TextIO.openString line
in
if (ch = #”p” andalso second = #”u”) then parseHelper(TextIO.input1(TextIO.openString (String.extract(line,4,NONE))), TextIO.openString (String.extract(line, 5, NONE)))
else if (Char.isDigit(ch)) then parseNumber(ord(ch)-ord(#”0″),inStr1)
else if (ch = #”-“) then parseNegativeNumber(inStr1)
else if (ch = #”:”) then parseBooleanOrError(“:”, inStr1)
else if (ch = #”\””) then parseString(“”, inStr1)
else if (Char.isAlpha(ch)) then parsePrimitive(Char.toString(ch), inStr1)
else if (ch = #”\n”) then parseHelper(TextIO.input1(inStr1), inStr1)
else NONE
end;
(* Function to parse the next expression on the input stream. *)
fun parse(inStr) = parseHelper(TextIO.input1(inStr), inStr);
fun hw4(inFile : string, outFile : string) =
let
val fileInp = TextIO.openIn inFile
val fileOut = TextIO.openOut outFile
fun printStack([]) = ()
| printStack(x::xs) = ( TextIO.output (fileOut, (expression2string(x)^”\n”)) ; printStack(xs) );
fun replHelper(inStr, (stack,env)) =
(
case (parse(inStr)) of
NONE => replHelper(inStr, (stack,env))
| SOME(Quit) => (printStack(stack); TextIO.closeIn fileInp; TextIO.closeOut fileOut)
| SOME(expression) => replHelper(inStr,eval(expression, stack,env))
);
in
replHelper(fileInp, ([],[[]]))
end
val _ = hw3(“input.txt”, “output.txt”)