// Prefix.java: translates to prefix form
import java.io.*;
public class Prefix {
PrefixScan S;
char next = 0;
// Prefix: constructor providing input file name
public Prefix(PrefixScan s) {
S = s;
}
public void Trans() {
String res;
res = P();
System.out.println(res);
}
private String P() {
String res;
Scan();
res = E();
if (next != '#') Error(1);
return res;
}
private String E() {
char save;
String res, arg1, arg2;
res = T();
while (next == '+' || next == '-') {
save = next;
arg1 = res;
Scan();
arg2 = T();
res = "(" + save + " " + arg1 + " " + arg2 + ")";
}
return res;
}
private String T() {
char save;
String res, arg1, arg2;
res = S();
while (next == '*' || next == '/') {
save = next;
arg1 = res;
Scan();
arg2 = S();
res = "(" + save + " " + arg1 + " " + arg2 + ")";
}
return res;
}
private String S() {
String res, arg1, arg2;
res = F();
if (next == '^') {
arg1 = res;
Scan();
arg2 = S();
res = "(^ " + arg1 + " " + arg2 + ")";
}
return res;
}
private String F() {
char save;
String res;
if (Character.isLetter(next) ||
Character.isDigit(next) ) {
save = next;
Scan();
res = save + "";
}
else if (next == '(') {
Scan();
res = E();
if (next == ')') Scan();
else Error(3);
}
else {
Error(4); res = "keep compiler happy";
}
return res;
}
private void Scan() {
char ch;
do {
ch = S.getNextChar();
if (ch == 65535) System.exit(0);
} while (Character.isWhitespace((char)ch));
next = (char)ch;
}
private void Error(int n) {
System.out.println("\n*** ERROR *** " + n);
System.exit(1);
}
}
// PrefixScan.java: fetch next character
import java.io.*;
public class PrefixScan {
private Reader in; // internal file name for input stream
private boolean fileOpen = false; // is the file open yet?
private String fileName; // name of input file, if present
private char ch; // holds next char
// PrefixScan(): constructor providing no input file name
public PrefixScan() {
fileName = "";
}
// PrefixScan(String ): constructor providing input file name
public PrefixScan(String f) {
fileName = f;
}
// getNextChar: fetches next char. Also opens input file
public char getNextChar() {
if (!fileOpen) {
try {
fileOpen = true;
if (fileName == "")
in = new InputStreamReader(System.in);
else
in = new FileReader(fileName);
}
catch (IOException exception) {
System.out.println("Error opening file");
System.exit(1);
}
}
try {
ch = (char)in.read();
}
catch (IOException exception) {
System.out.println("Error reading character");
ch = ' ';
}
return ch;
}
}
// PrefixTest.java: Test the translator to prefix code
import java.io.*;
public class PrefixTest {
public static void main(String[] args) {
PrefixScan S; // the scanner
Prefix P; // the translator
// pass an input file name if present on command line
if (args.length > 0)
S = new PrefixScan(args[0]);
else
S = new PrefixScan();
P = new Prefix(S);
P.Trans();
}
}
ten42% java PrefixTest
2+3*4#
(+ 2 (* 3 4))
ten42% java PrefixTest
3*4+5#
(+ (* 3 4) 5)
ten42% java PrefixTest
(2+3)*4#
(* (+ 2 3) 4)
ten42% java PrefixTest
(3*(2+4)/(5+1))-2#
(- (/ (* 3 (+ 2 4)) (+ 5 1)) 2)
ten42% java PrefixTest
(5+3)^(2+1)^2#
(^ (+ 5 3) (^ (+ 2 1) 2))
ten42% java PrefixTest
2+3*4^5*6+7#
(+ (+ 2 (* (* 3 (^ 4 5)) 6)) 7)
ten42% java PrefixTest
2 + (3*(4^5)*6) + 7#
(+ (+ 2 (* (* 3 (^ 4 5)) 6)) 7)
ten42% java PrefixTest
((3^2-4*1*2)^(1/2)-3)/(2*1)#
(/ (- (^ (- (^ 3 2) (* (* 4 1) 2)) (/ 1 2)) 3) (* 2 1))
ten42% java PrefixTest
((2-3)^((4+1)*5)/6-(2-4)*7)-8#
(- (- (/ (^ (- 2 3) (* (+ 4 1) 5)) 6) (* (- 2 4) 7)) 8)
ten42% java PrefixTest
3^4^2#
(^ 3 (^ 4 2))
ten42% java PrefixTest
3^(4^2)#
(^ 3 (^ 4 2))
ten42% java PrefixTest
(3^4)^2#
(^ (^ 3 4) 2)
ten42% java PrefixTest
9 - 5 - 3 #
(- (- 9 5) 3)
ten42% java PrefixTest
8/3/5#
(/ (/ 8 3) 5)
ten42% java PrefixTest
8/(3/5)#
(/ 8 (/ 3 5))
ten42% java PrefixTest
3+1/(7+1/(5*3+1/(1+1/((4*(9*8+1)) ))))#
(+ 3 (/ 1 (+ 7 (/ 1 (+ (* 5 3) (/ 1 (+ 1 (/ 1 (* 4 (+ (* 9 8) 1))))))))))
ten42% java PrefixTest
3+1/(7+1/(5*3+1/(1+1/((4*(9*8+1))+1/(1+1/(1+1/(1+1/(2
+1/(1+1/(3+1/(1+1/(2*7+1/(2+1) ))))))))))))#
(+ 3 (/ 1 (+ 7 (/ 1 (+ (* 5 3) (/ 1 (+ 1 (/ 1 (+ (* 4 (+ (* 9 8) 1)) (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 2 (/ 1 (+ 1 (/ 1 (+ 3 (/ 1 (+ 1 (/ 1 (+ (* 2 7) (/ 1 (+ 2 1)))))))))))))))))))))))))))
ten42% java PrefixTest
1+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1
/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2+1/(2
))))))))))))))))))))#
(+ 1 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 (+ 2 (/ 1 2))))))))))))))))))))))))))))))))))))))))
ten42% java PrefixTest
2+1/(1+1/(2+1/(1+1/(1+1/(4+1/(1+1/(1+1/(6+1/(1+1/(1+1
/(8+1/(1+1/(1+1/(2*5+1/(1+1/(1+1/(2*6+1/(1+1/(1+1/(2*
7+1 ))))))))))))))))))))#
(+ 2 (/ 1 (+ 1 (/ 1 (+ 2 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 4 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 6 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 8 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ (* 2 5) (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ (* 2 6) (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ (* 2 7) 1)))))))))))))))))))))))))))))))))))))))))
ten42% java PrefixTest
1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1+1
)))))))))))))))))))))))))))))))))))#
(+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 1 1)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
In each case above, the prefix output was fed into Lisp and gave
exactly the same result as with the evaluator.
(It was necessary to translate "^" to "expt" and to change one
"1" to a "1.0" in each expression to force evaluation as
a floating point number, rather than as a fraction.)