Skip to content

Commit ca6bb17

Browse files
committed
 ✨ working interpreter for the new grammar
1 parent 494bcc6 commit ca6bb17

File tree

8 files changed

+105
-25
lines changed

8 files changed

+105
-25
lines changed

Playground.playground/Contents.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ lexer.getNextToken()
1616
let program =
1717
"""
1818
PROGRAM Part10AST;
19-
BEGIN
20-
BEGIN
21-
number := 2;
22-
a := number;
23-
b := 10 * a + 10 * number / 4;
24-
c := a - - b
25-
END;
26-
x := 11;
27-
END.
19+
VAR
20+
a, b : INTEGER;
21+
y : REAL;
22+
23+
BEGIN {Part10AST}
24+
a := 2;
25+
b := 10 * a + 10 * a DIV 4;
26+
y := 20 / 7 + 3.14;
27+
END. {Part10AST}
2828
"""
2929

3030
let parser = Parser(program)

SwiftPascalInterpreter/SwiftPascalInterpreter/Extensions/AST+Extensions.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ extension AST {
113113
var nodes = declarations
114114
nodes.append(compound)
115115
return nodes
116-
case .variableDeclaration:
117-
return []
116+
case let .variableDeclaration(name: name, type: type):
117+
return [name, type]
118118
case .type:
119119
return []
120120
case let .program(_, block):
@@ -140,8 +140,8 @@ extension AST {
140140
return ":="
141141
case .block:
142142
return "block"
143-
case let .variableDeclaration(name, type):
144-
return "\(name): \(type.description)"
143+
case .variableDeclaration:
144+
return "var"
145145
case let .type(type):
146146
return type.description
147147
case let .program(name, _):

SwiftPascalInterpreter/SwiftPascalInterpreter/Extensions/Token+Extensions.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ extension Token: Equatable {
5353
return true
5454
case let (.integerConst(left), .integerConst(right)):
5555
return left == right
56+
case let (.realConst(left), .realConst(right)):
57+
return left == right
5658
default:
5759
return false
5860
}

SwiftPascalInterpreter/SwiftPascalInterpreter/Interpreter.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,17 @@ public class Interpreter {
6666
return value
6767
case .noOp:
6868
return nil
69-
default:
69+
case .block(let declarations, let compound):
70+
for declaration in declarations {
71+
visit(declaration)
72+
}
73+
return visit(compound)
74+
case .variableDeclaration:
75+
return nil
76+
case .type:
7077
return nil
78+
case let .program(_, block):
79+
return visit(block)
7180
}
7281
}
7382

SwiftPascalInterpreter/SwiftPascalInterpreter/Model/AST.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public enum AST {
3535
case variable(String)
3636
case noOp
3737
indirect case block(declarations: [AST], compound: AST)
38-
indirect case variableDeclaration(name: String, type: AST)
38+
indirect case variableDeclaration(name: AST, type: AST)
3939
case type(Type)
4040
indirect case program(name: String, block: AST)
4141
}

SwiftPascalInterpreter/SwiftPascalInterpreter/Parser.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public class Parser {
108108
eat(.colon)
109109

110110
let type = typeSpec()
111-
return variableNames.map({ .variableDeclaration(name: $0, type: type) })
111+
return variableNames.map({ .variableDeclaration(name: .variable($0), type: type) })
112112
}
113113

114114
/**
@@ -118,8 +118,10 @@ public class Parser {
118118
private func typeSpec() -> AST {
119119
switch currentToken {
120120
case .integer:
121+
eat(.integer)
121122
return .type(.integer)
122123
case .real:
124+
eat(.real)
123125
return .type(.real)
124126
default:
125127
fatalError("Expected type, got \(currentToken)")

SwiftPascalInterpreter/SwiftPascalInterpreterTests/InterpreterTests.swift

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,25 @@ import Foundation
1212
import XCTest
1313

1414
class InterpreterTests: XCTestCase {
15-
func testSimpleDeclaration() {
16-
let interpeter = Interpreter("BEGIN a := 2; END.")
15+
func testSimpleProgram() {
16+
let program =
17+
"""
18+
PROGRAM Part10AST;
19+
BEGIN
20+
a := 2
21+
END.
22+
"""
23+
24+
let interpeter = Interpreter(program)
1725
interpeter.interpret()
1826
let state = interpeter.getState()
1927
XCTAssert(state == ["a": 2])
2028
}
2129

22-
func testComplexDeclaration() {
30+
func testMoreComplexProgram() {
2331
let program =
2432
"""
33+
PROGRAM Part10AST;
2534
BEGIN
2635
BEGIN
2736
number := 2;
@@ -38,4 +47,25 @@ class InterpreterTests: XCTestCase {
3847
let state = interpeter.getState()
3948
XCTAssert(state == ["b": 25, "number": 2, "a": 2, "x": 11, "c": 27])
4049
}
50+
51+
func testProgramWithDeclarations() {
52+
let program =
53+
"""
54+
PROGRAM Part10AST;
55+
VAR
56+
a, b : INTEGER;
57+
y : REAL;
58+
59+
BEGIN {Part10AST}
60+
a := 2;
61+
b := 10 * a + 10 * a DIV 4;
62+
y := 20 / 7 + 3.14;
63+
END. {Part10AST}
64+
"""
65+
66+
let interpeter = Interpreter(program)
67+
interpeter.interpret()
68+
let state = interpeter.getState()
69+
XCTAssert(state == ["b": 25, "number": 2, "a": 2, "x": 11, "c": 27])
70+
}
4171
}

SwiftPascalInterpreter/SwiftPascalInterpreterTests/ParserTests.swift

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import XCTest
1313
class ParserTests: XCTestCase {
1414
func testBasicCompoundStatement() {
1515
let program =
16-
"""
17-
PROGRAM Part10AST;
18-
BEGIN
19-
a := 2
20-
END.
21-
"""
16+
"""
17+
PROGRAM Part10AST;
18+
BEGIN
19+
a := 2
20+
END.
21+
"""
2222

2323
let a = AST.variable("a")
2424
let two = AST.number(2)
@@ -89,4 +89,41 @@ class ParserTests: XCTestCase {
8989
let node = AST.program(name: "Part10AST", block: AST.block(declarations: [], compound: AST.compound(children: [compound, xAssignment, empty])))
9090
XCTAssert(result == node)
9191
}
92+
93+
func testProgramWithDeclarationsExpression() {
94+
let program =
95+
"""
96+
PROGRAM Part10AST;
97+
VAR
98+
a, b : INTEGER;
99+
y : REAL;
100+
BEGIN
101+
BEGIN
102+
number := 2;
103+
a := number;
104+
a := 10 * a + 10 * number / 4;
105+
END;
106+
x := 11;
107+
END.
108+
"""
109+
110+
let parser = Parser(program)
111+
let result = parser.parse()
112+
let empty = AST.noOp
113+
let eleven = AST.number(11)
114+
let x = AST.variable("x")
115+
let xAssignment = AST.assignment(left: x, right: eleven)
116+
let two = AST.number(2)
117+
let number = AST.variable("number")
118+
let a = AST.variable("a")
119+
let division = AST.binaryOperation(left: AST.binaryOperation(left: AST.number(10), operation: .mult, right: number), operation: .floatDiv, right: AST.number(4))
120+
let plus = AST.binaryOperation(left: AST.binaryOperation(left: AST.number(10), operation: .mult, right: a), operation: .plus, right: division)
121+
let aAssignment = AST.assignment(left: a, right: plus)
122+
let compound = AST.compound(children: [AST.assignment(left: number, right: two), AST.assignment(left: a, right: number), aAssignment, empty])
123+
let aDec = AST.variableDeclaration(name: AST.variable("a"), type: .type(.integer))
124+
let bDec = AST.variableDeclaration(name: AST.variable("b"), type: .type(.integer))
125+
let yDec = AST.variableDeclaration(name: AST.variable("y"), type: .type(.real))
126+
let node = AST.program(name: "Part10AST", block: AST.block(declarations: [aDec, bDec, yDec], compound: AST.compound(children: [compound, xAssignment, empty])))
127+
XCTAssert(result == node)
128+
}
92129
}

0 commit comments

Comments
 (0)