Skip to content

Commit 18b152e

Browse files
committed
✨ Parser working for the new grammar
1 parent de36dbd commit 18b152e

File tree

6 files changed

+46
-16
lines changed

6 files changed

+46
-16
lines changed

Playground.playground/Contents.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ lexer.getNextToken()
1515

1616
let program =
1717
"""
18+
PROGRAM Part10AST;
1819
BEGIN
1920
BEGIN
2021
number := 2;

SwiftPascalInterpreter/SwiftPascalInterpreter/Extensions/AST+Extensions.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ extension AST: Equatable {
3939
return leftDeclarations == rightDeclarations && leftCompound == rightCompound
4040
case let (.variableDeclaration(name: leftName, type: leftType), .variableDeclaration(name: rightName, type: rightType)):
4141
return leftName == rightName && leftType == rightType
42+
case let (.program(name: leftName, block: leftBlock), .program(name: rightName, block: rightBlock)):
43+
return leftName == rightName && leftBlock == rightBlock
4244
default:
4345
return false
4446
}
@@ -115,6 +117,8 @@ extension AST {
115117
return []
116118
case .type:
117119
return []
120+
case let .program(_, block):
121+
return [block]
118122
}
119123
}
120124

@@ -140,6 +144,8 @@ extension AST {
140144
return "\(name): \(type.description)"
141145
case let .type(type):
142146
return type.description
147+
case let .program(name, _):
148+
return name
143149
}
144150
}
145151

SwiftPascalInterpreter/SwiftPascalInterpreter/Model/AST.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ public enum AST {
3737
indirect case block(declarations: [AST], compound: AST)
3838
indirect case variableDeclaration(name: String, type: AST)
3939
case type(Type)
40+
indirect case program(name: String, block: AST)
4041
}

SwiftPascalInterpreter/SwiftPascalInterpreter/Parser.swift

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,19 @@ public class Parser {
4141
/**
4242
Rule:
4343

44-
program : compound_statement DOT
44+
program : PROGRAM variable SEMI block DOT
4545
*/
4646
private func program() -> AST {
47-
let node = compoundStatement()
47+
eat(.program)
48+
guard case let .id(name) = currentToken else {
49+
fatalError("Program must have a name")
50+
}
51+
eat(.id(name))
52+
eat(.semi)
53+
let blockNode = block()
54+
let programNode = AST.program(name: name, block: blockNode)
4855
eat(.dot)
49-
return node
56+
return programNode
5057
}
5158

5259
/**
@@ -213,22 +220,22 @@ public class Parser {
213220
/**
214221
Rule:
215222

216-
term: factor ((MUL | DIV) factor)*
223+
term : factor ((MUL | INTEGER_DIV | FLOAT_DIV) factor)*
217224
*/
218225
private func term() -> AST {
219226
var node = factor()
220227

221-
while [.mult, .floatDiv, .integerDiv].contains(currentToken) {
228+
while [.mult, .integerDiv, .floatDiv].contains(currentToken) {
222229
let token = currentToken
223230
if token == .mult {
224231
eat(.mult)
225232
node = .binaryOperation(left: node, operation: .mult, right: factor())
226-
} else if token == .floatDiv {
227-
eat(.floatDiv)
228-
node = .binaryOperation(left: node, operation: .floatDiv, right: factor())
229233
} else if token == .integerDiv {
230234
eat(.integerDiv)
231235
node = .binaryOperation(left: node, operation: .integerDiv, right: factor())
236+
} else if token == .floatDiv {
237+
eat(.floatDiv)
238+
node = .binaryOperation(left: node, operation: .floatDiv, right: factor())
232239
}
233240
}
234241

@@ -253,9 +260,10 @@ public class Parser {
253260
/**
254261
Rule:
255262

256-
factor : PLUS factor
263+
factor : PLUS factor
257264
| MINUS factor
258-
| INTEGER
265+
| INTEGER_CONST
266+
| REAL_CONST
259267
| LPAREN expr RPAREN
260268
| variable
261269
*/
@@ -271,6 +279,9 @@ public class Parser {
271279
case let .integerConst(value):
272280
eat(.integerConst(value))
273281
return .number(value)
282+
case let .realConst(value):
283+
eat(.realConst(value))
284+
return .number(Int(value.rounded(.toNearestOrEven))) //TODO: proper real types
274285
case .lparen:
275286
eat(.lparen)
276287
let result = expr()

SwiftPascalInterpreter/SwiftPascalInterpreterTests/LexerTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ class LexerTests: XCTestCase {
233233
if case let .realConst(value) = lexer.getNextToken() {
234234
XCTAssert(abs(3.14 - value) < 0.01)
235235
} else {
236-
XCTFail()
236+
XCTFail("Given value differes from expected 3.14")
237237
}
238238
XCTAssert(lexer.getNextToken() == .eof)
239239
}

SwiftPascalInterpreter/SwiftPascalInterpreterTests/ParserTests.swift

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,28 @@ import XCTest
1212

1313
class ParserTests: XCTestCase {
1414
func testBasicCompoundStatement() {
15+
let program =
16+
"""
17+
PROGRAM Part10AST;
18+
BEGIN
19+
a := 2
20+
END.
21+
"""
22+
1523
let a = AST.variable("a")
1624
let two = AST.number(2)
1725
let assignment = AST.assignment(left: a, right: two)
18-
let empty = AST.noOp
19-
let node = AST.compound(children: [assignment, empty])
20-
let parser = Parser("BEGIN a := 2; END.")
26+
let block = AST.block(declarations: [], compound: AST.compound(children: [assignment]))
27+
let node = AST.program(name: "Part10AST", block: block)
28+
let parser = Parser(program)
2129
let result = parser.parse()
2230
XCTAssert(result == node)
2331
}
2432

2533
func testMoreComplexExpression() {
2634
let program =
2735
"""
36+
PROGRAM Part10AST;
2837
BEGIN
2938
BEGIN
3039
number := 2;
@@ -45,13 +54,15 @@ class ParserTests: XCTestCase {
4554
let a = AST.variable("a")
4655
let aAssignment = AST.assignment(left: a, right: AST.binaryOperation(left: number, operation: .plus, right: two))
4756
let compound = AST.compound(children: [AST.assignment(left: number, right: two), aAssignment, empty])
48-
let node = AST.compound(children: [compound, xAssignment, empty])
57+
let block = AST.block(declarations: [], compound: AST.compound(children: [compound, xAssignment, empty]))
58+
let node = AST.program(name: "Part10AST", block: block)
4959
XCTAssert(result == node)
5060
}
5161

5262
func testEvenMoreComplexExpression() {
5363
let program =
5464
"""
65+
PROGRAM Part10AST;
5566
BEGIN
5667
BEGIN
5768
number := 2;
@@ -75,7 +86,7 @@ class ParserTests: XCTestCase {
7586
let plus = AST.binaryOperation(left: AST.binaryOperation(left: AST.number(10), operation: .mult, right: a), operation: .plus, right: division)
7687
let aAssignment = AST.assignment(left: a, right: plus)
7788
let compound = AST.compound(children: [AST.assignment(left: number, right: two), AST.assignment(left: a, right: number), aAssignment, empty])
78-
let node = AST.compound(children: [compound, xAssignment, empty])
89+
let node = AST.program(name: "Part10AST", block: AST.block(declarations: [], compound: AST.compound(children: [compound, xAssignment, empty])))
7990
XCTAssert(result == node)
8091
}
8192
}

0 commit comments

Comments
 (0)