Inspired by Dan's question on Stack Overflow.
Given this "program", the Stack will have one number at the top (i.e. 12).
( 3 * 4 ) .
/*
* Copyright © 2013 - Elliott Frisch
*
* THIS SOFTWARE IS PROVIDED UNDER THE CREATIVE COMMONS
* LICENSE 3.0 "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
* A PARTICULAR PURPOSE.
*
* To use this software you must agree to the complete
* license terms available at:
* http://creativecommons.org/licenses/by/3.0/us/deed.en_US
*
* It is the intent of the author(s) that you may use or
* modify this software for any purpose (including your own
* commercial gain) provided that this notice remains in its
* entirety.
*
* Created by Elliott Frisch - www.frischcode.com
* Daniel Brackett - www.danielbrackett.com
*/
package com.frischcode.util;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* <b>Rationale:</b> Implementing a basic Stack. Then
* demonstrate an arbitrary precision math REPL with two
* unbounded Stacks. Inspired by <a
* href="http://stackoverflow.com/users/1516132/dan"
* >Dan</a>'s question on <a href=
* "http://stackoverflow.com/questions/19988147/stack-adding-machine-0doesnt-add-but-hangs-waiting-for-more-args"
* >Stack Overflow</a>.
*
* @author Elliott Frisch
*
* @param <T>
* A generic stack container.
*/
public class Stack<T> {
private static final String UNDERFLOW = "Stack underflow error. Continuing.";
private static final String OVERFLOW = "Stack over-flow error. Continuing.";
private static final void say(String in) {
if (in != null) {
if (in.length() > 0) {
System.out.println(in);
System.out.flush();
}
}
}
private static final void underFlow() {
say(UNDERFLOW);
}
private static final void overFlow() {
say(OVERFLOW);
}
private enum Operators {
ADD("+"), SUB("-"), MULTIPLY("*"), DIVIDE("/"), POW(
"^");
Operators(String oper) {
_oper = oper;
}
private String _oper;
public String toString() {
return _oper;
}
public BigDecimal execute(BigDecimal a,
BigDecimal b) {
switch (this) {
case ADD:
return a.add(b);
case SUB:
return b.subtract(a);
case MULTIPLY:
return a.multiply(b);
case DIVIDE:
return b.divide(a);
case POW:
return a.pow(b.intValue());
}
return null;
}
public static Operators matchOper(String in) {
if (in != null) {
in = in.trim();
for (Operators oper : Operators.values()) {
if (oper.toString().equals(in)) {
return oper;
}
}
}
return null;
}
}
private List<T> a;
public static void main(String[] args) {
Stack<String> ops = new Stack<String>(5);
Stack<BigDecimal> vals = new Stack<BigDecimal>(100);
say("REPL loaded - BEGIN");
Scanner console = new Scanner(System.in);
try {
while (console.hasNext()) {
String str = console.next().trim();
if (str.equals(".")) {
say(vals.peek().toString());
} else if (str.equals("(")) {
;
} else if (Operators.matchOper(str) != null) {
ops.push(str);
} else if (str.equals(")") || str.equals("=")) {
Operators op = Operators
.matchOper(ops.pop());
if (op != null) {
BigDecimal a = vals.pop();
BigDecimal b = vals.pop();
if (a != null && b != null) {
a = op.execute(a, b);
}
if (a != null) {
vals.push(a);
}
}
} else {
try {
final BigDecimal a = new BigDecimal(str);
if (a != null) {
vals.push(a);
}
} catch (Exception e) {
say(e.getMessage() + ": " + str);
}
}
}
} finally {
console.close();
}
}
/**
* Construct an Empty Stack. Default to an initial
* capacity of 10.
*/
public Stack() {
this(10);
}
/**
* Construct a Stack with an initial capacity of cap.
*
* @param cap
* An initial capacity size.
*/
public Stack(int cap) {
a = new ArrayList<T>(cap);
}
/**
* Pushes an Item onto this Stack. Ignores null.
*
* @param item
* The item to push onto the stack.
*/
public void push(T item) {
if (item != null && !isFull()) {
a.add(item);
} else {
overFlow();
}
}
/**
* Pops the top item off the stack. Null if empty.
*
* @return The top item on the stack. Removes it.
*/
public T pop() {
if (!isEmpty()) {
return a.remove(a.size() - 1);
}
underFlow();
return null;
}
/**
* Returns the item at the top of the Stack. That is what
* pop() would return without modifying the Stack.
*
* @return The top item on the stack. Without removing it.
*/
public T peek() {
if (!isEmpty()) {
return a.get(a.size() - 1);
}
underFlow();
return null;
}
/**
* This Stack is unbounded.
*
* @return return false.
*/
public boolean isFull() {
return false;
}
/**
* Return true if the Stack doesn't have any items.
*
* @return true if the Stack contains no items.
*/
public boolean isEmpty() {
return a.size() == 0;
}
/**
* The size of the stack + 1.
*
* @return The size of the Stack + 1.
*/
public int size() {
return a.size();
}
}
No comments :
Post a Comment