Skip to content

Commit d6fdec5

Browse files
committed
✨ adding support for unary operations
1 parent 20ba190 commit d6fdec5

File tree

8 files changed

+53
-1
lines changed

8 files changed

+53
-1
lines changed

SwiftPascalInterpreter/SwiftPascalInterpreter/AST.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ import Foundation
1010

1111
public enum AST {
1212
case number(Int)
13+
indirect case unaryOperation(operation: Operation, child: AST)
1314
indirect case binaryOperation(left: AST, operation: Operation, right: AST)
1415
}

SwiftPascalInterpreter/SwiftPascalInterpreter/Extensions.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ extension AST: CustomStringConvertible {
121121
switch node {
122122
case let .number(value):
123123
return ("\(value)", nil, nil)
124+
case let .unaryOperation(operation: operation, child: child):
125+
return ("u\(operation.shortDescription)", child, nil)
124126
case let .binaryOperation(left: left, operation: operation, right: right):
125127
return ("\(operation.shortDescription)", left, right)
126128
}
@@ -133,6 +135,8 @@ extension AST: Equatable {
133135
switch (lhs, rhs) {
134136
case let (.number(left), .number(right)):
135137
return left == right
138+
case let (.unaryOperation(operation: leftOperation, child: leftChild), .unaryOperation(operation: rightOperation, child: rightChild)):
139+
return leftOperation == rightOperation && leftChild == rightChild
136140
case let (.binaryOperation(left: leftLeft, operation: leftOperation, right: leftRight), .binaryOperation(left: rightLeft, operation: rightOperation, right: rightRight)):
137141
return leftLeft == rightLeft && leftOperation == rightOperation && leftRight == rightRight
138142
default:

SwiftPascalInterpreter/SwiftPascalInterpreter/Interpreter.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ public class Interpreter {
2424
switch node {
2525
case let .number(value):
2626
return value
27+
case let .unaryOperation(operation: operation, child: child):
28+
switch operation {
29+
case .plus:
30+
return +visit(child)
31+
case .minus:
32+
return -visit(child)
33+
default:
34+
fatalError("Unsupported unary operation \(operation)")
35+
}
2736
case let .binaryOperation(left: left, operation: operation, right: right):
2837
switch operation {
2938
case .plus:

SwiftPascalInterpreter/SwiftPascalInterpreter/Notations.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class RPN: Notation {
3131
switch node {
3232
case let .number(value):
3333
return "\(value)"
34+
case let .unaryOperation(operation: operation, child: child):
35+
return "\(visit(child)) \(operation.shortDescription)"
3436
case let .binaryOperation(left: left, operation: operation, right: right):
3537
return "\(visit(left)) \(visit(right)) \(operation.shortDescription)"
3638
}
@@ -56,6 +58,8 @@ public class LISPNotation: Notation {
5658
switch node {
5759
case let .number(value):
5860
return "\(value)"
61+
case let .unaryOperation(operation: operation, child: child):
62+
return "(\(operation.shortDescription) \(visit(child)))"
5963
case let .binaryOperation(left: left, operation: operation, right: right):
6064
return "(\(operation.shortDescription) \(visit(left)) \(visit(right)))"
6165
}

SwiftPascalInterpreter/SwiftPascalInterpreter/Parser.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ public class Parser {
4646
let result = expr()
4747
eat(.parenthesis(.right))
4848
return result
49+
case .operation(.plus):
50+
eat(.operation(.plus))
51+
return .unaryOperation(operation: .plus, child: factor())
52+
case .operation(.minus):
53+
eat(.operation(.minus))
54+
return .unaryOperation(operation: .minus, child: factor())
4955
default:
5056
fatalError("Syntax error")
5157
}
@@ -78,7 +84,7 @@ public class Parser {
7884

7985
expr : term (PLUS | MINUS) term)*
8086
term : factor ((MUL | DIV) factor)*
81-
factor : INTEGER | LPAREN factor RPAREN
87+
factor : (PLUS | MINUS) factor | INTEGER | LPAREN factor RPAREN
8288

8389
Returns: AST node
8490
*/

SwiftPascalInterpreter/SwiftPascalInterpreterTests/InterpreterTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ class InterpreterTests: XCTestCase {
3030
XCTAssert(Interpreter("7 + 3 * (10 / (12 / (3 + 1) - 1)) / (2 + 3) - 5 - 3 + (8)").eval() == 10)
3131
XCTAssert(Interpreter("7 + (((3 + 2)))").eval() == 12)
3232
}
33+
34+
func testUnaryOperations() {
35+
let interpeter = Interpreter("5 - - -2")
36+
let result = interpeter.eval()
37+
XCTAssert(result == 3)
38+
}
3339
}

SwiftPascalInterpreter/SwiftPascalInterpreterTests/LexerTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,15 @@ class LexerTests: XCTestCase {
155155
XCTAssert(lexer.getNextToken() == .parenthesis(.right))
156156
XCTAssert(lexer.getNextToken() == .eof)
157157
}
158+
159+
func testUnaryOperators() {
160+
let lexer = Lexer("5 - - - 2")
161+
162+
XCTAssert(lexer.getNextToken() == .integer(5))
163+
XCTAssert(lexer.getNextToken() == .operation(.minus))
164+
XCTAssert(lexer.getNextToken() == .operation(.minus))
165+
XCTAssert(lexer.getNextToken() == .operation(.minus))
166+
XCTAssert(lexer.getNextToken() == .integer(2))
167+
XCTAssert(lexer.getNextToken() == .eof)
168+
}
158169
}

SwiftPascalInterpreter/SwiftPascalInterpreterTests/ParserTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,15 @@ class ParserTests: XCTestCase {
5656
let result = parser.expr()
5757
XCTAssert(result == node)
5858
}
59+
60+
func testUnaryOperatorNodesNodes() {
61+
let five = AST.number(5)
62+
let two = AST.number(2)
63+
let un1 = AST.unaryOperation(operation: .minus, child: two)
64+
let un2 = AST.unaryOperation(operation: .minus, child: un1)
65+
let node = AST.binaryOperation(left: five, operation: .minus, right: un2)
66+
let parser = Parser("5 - - - 2")
67+
let result = parser.expr()
68+
XCTAssert(result == node)
69+
}
5970
}

0 commit comments

Comments
 (0)