| 
219
 | 
     1  | 
// Shunting Yard Algorithm
  | 
| 
 | 
     2  | 
// by Edsger Dijkstra
  | 
| 
 | 
     3  | 
// ========================
  | 
| 
 | 
     4  | 
  | 
| 
346
 | 
     5  | 
object CW8a {
 | 
| 
219
 | 
     6  | 
  | 
| 
220
 | 
     7  | 
// type of tokens
  | 
| 
219
 | 
     8  | 
type Toks = List[String]
  | 
| 
 | 
     9  | 
  | 
| 
220
 | 
    10  | 
// the operations in the basic version of the algorithm
  | 
| 
219
 | 
    11  | 
val ops = List("+", "-", "*", "/")
 | 
| 
 | 
    12  | 
  | 
| 
 | 
    13  | 
// the precedences of the operators
  | 
| 
 | 
    14  | 
val precs = Map("+" -> 1,
 | 
| 
 | 
    15  | 
		"-" -> 1,
  | 
| 
 | 
    16  | 
		"*" -> 2,
  | 
| 
 | 
    17  | 
		"/" -> 2)
  | 
| 
 | 
    18  | 
  | 
| 
 | 
    19  | 
// helper function for splitting strings into tokens
  | 
| 
 | 
    20  | 
def split(s: String) : Toks = s.split(" ").toList
 | 
| 
 | 
    21  | 
  | 
| 
 | 
    22  | 
  | 
| 
288
 | 
    23  | 
// (1) Implement below the shunting yard algorithm. The most
  | 
| 
219
 | 
    24  | 
// convenient way to this in Scala is to implement a recursive 
  | 
| 
220
 | 
    25  | 
// function and to heavily use pattern matching. The function syard 
  | 
| 
 | 
    26  | 
// takes some input tokens as first argument. The second and third 
  | 
| 
 | 
    27  | 
// arguments represent the stack and the output of the shunting yard 
  | 
| 
 | 
    28  | 
// algorithm.
  | 
| 
219
 | 
    29  | 
//
  | 
| 
 | 
    30  | 
// In the marking, you can assume the function is called only with 
  | 
| 
220
 | 
    31  | 
// an empty stack and an empty output list. You can also assume the
  | 
| 
 | 
    32  | 
// input os  only properly formatted (infix) arithmetic expressions
  | 
| 
 | 
    33  | 
// (all parentheses will be well-nested, the input only contains 
  | 
| 
219
 | 
    34  | 
// operators and numbers).
  | 
| 
 | 
    35  | 
  | 
| 
220
 | 
    36  | 
// You can implement any additional helper function you need. I found 
  | 
| 
 | 
    37  | 
// it helpful to implement two auxiliary functions for the pattern matching:  
  | 
| 
 | 
    38  | 
// 
  | 
| 
346
 | 
    39  | 
  | 
| 
 | 
    40  | 
def is_op(op: String) : Boolean = ???
  | 
| 
 | 
    41  | 
def prec(op1: String, op2: String) : Boolean = ???
  | 
| 
219
 | 
    42  | 
  | 
| 
 | 
    43  | 
  | 
| 
346
 | 
    44  | 
def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = ???
  | 
| 
219
 | 
    45  | 
  | 
| 
 | 
    46  | 
  | 
| 
 | 
    47  | 
// test cases
  | 
| 
 | 
    48  | 
//syard(split("3 + 4 * ( 2 - 1 )"))  // 3 4 2 1 - * +
 | 
| 
 | 
    49  | 
//syard(split("10 + 12 * 33"))       // 10 12 33 * +
 | 
| 
 | 
    50  | 
//syard(split("( 5 + 7 ) * 2"))      // 5 7 + 2 *
 | 
| 
 | 
    51  | 
//syard(split("5 + 7 / 2"))          // 5 7 2 / +
 | 
| 
 | 
    52  | 
//syard(split("5 * 7 / 2"))          // 5 7 * 2 /
 | 
| 
 | 
    53  | 
//syard(split("9 + 24 / ( 7 - 3 )")) // 9 24 7 3 - / +
 | 
| 
 | 
    54  | 
  | 
| 
 | 
    55  | 
//syard(split("3 + 4 + 5"))           // 3 4 + 5 +
 | 
| 
 | 
    56  | 
//syard(split("( ( 3 + 4 ) + 5 )"))    // 3 4 + 5 +
 | 
| 
 | 
    57  | 
//syard(split("( 3 + ( 4 + 5 ) )"))    // 3 4 5 + +
 | 
| 
 | 
    58  | 
//syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) // 3 4 5 + +
 | 
| 
 | 
    59  | 
  | 
| 
 | 
    60  | 
 
  | 
| 
288
 | 
    61  | 
// (2) Implement a compute function that evaluates an input list
  | 
| 
220
 | 
    62  | 
// in postfix notation. This function takes a list of tokens
  | 
| 
 | 
    63  | 
// and a stack as argumenta. The function should produce the 
  | 
| 
 | 
    64  | 
// result as an integer using the stack. You can assume 
  | 
| 
 | 
    65  | 
// this function will be only called with proper postfix 
  | 
| 
 | 
    66  | 
// expressions.    
  | 
| 
219
 | 
    67  | 
  | 
| 
346
 | 
    68  | 
def compute(toks: Toks, st: List[Int] = Nil) : Int = ???
  | 
| 
219
 | 
    69  | 
  | 
| 
 | 
    70  | 
  | 
| 
 | 
    71  | 
// test cases
  | 
| 
 | 
    72  | 
// compute(syard(split("3 + 4 * ( 2 - 1 )")))  // 7
 | 
| 
 | 
    73  | 
// compute(syard(split("10 + 12 * 33")))       // 406
 | 
| 
 | 
    74  | 
// compute(syard(split("( 5 + 7 ) * 2")))      // 24
 | 
| 
 | 
    75  | 
// compute(syard(split("5 + 7 / 2")))          // 8
 | 
| 
 | 
    76  | 
// compute(syard(split("5 * 7 / 2")))          // 17
 | 
| 
 | 
    77  | 
// compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
 | 
| 
 | 
    78  | 
  | 
| 
288
 | 
    79  | 
}
  | 
| 
219
 | 
    80  | 
  | 
| 
 | 
    81  | 
  |