Skip to content

Commit 5f8d38a

Browse files
committed
✨ Parser support for while loops
1 parent 71b68c4 commit 5f8d38a

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

PascalInterpreter/PascalInterpreter/Lexer/Lexer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class Lexer {
4343
"FOR": .for,
4444
"TO": .to,
4545
"DO": .do,
46-
"WHILE": .while
46+
"WHILE": .while,
4747
]
4848

4949
public init(_ text: String) {

PascalInterpreter/PascalInterpreter/Parser/Parser.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ public class Parser {
279279
| assignment_statement
280280
| repeat_until
281281
| for_loop
282+
| while_loop
282283
| empty
283284
*/
284285
private func statement() -> AST {
@@ -289,6 +290,8 @@ public class Parser {
289290
return ifElseStatement()
290291
case .repeat:
291292
return repeatUntilLoop()
293+
case .while:
294+
return whileLoop()
292295
case .for:
293296
return forLoop()
294297
case .id:
@@ -323,6 +326,19 @@ public class Parser {
323326
return RepeatUntil(statement: statements.count == 1 ? statements[0] : Compound(children: statements), condition: condition)
324327
}
325328

329+
/**
330+
Rule:
331+
332+
for_loop : WHILE condition DO statement
333+
*/
334+
private func whileLoop() -> While {
335+
eat(.while)
336+
let condition = self.condition()
337+
eat(.do)
338+
let statement = self.statement()
339+
return While(statement: statement, condition: condition)
340+
}
341+
326342
/**
327343
Rule:
328344

PascalInterpreter/PascalInterpreterTests/ParserTests.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,4 +469,27 @@ class ParserTests: XCTestCase {
469469
let node = Program(name: "Main", block: block)
470470
XCTAssertEqual(result, node)
471471
}
472+
473+
func testProgramWithWhileLoop() {
474+
let program =
475+
"""
476+
program Main;
477+
var x: integer;
478+
479+
begin
480+
x:=0;
481+
while x < 6 do
482+
x:=x+1;
483+
writeln(x);
484+
end. { Main }
485+
"""
486+
487+
let parser = Parser(program)
488+
let result = parser.parse()
489+
let xDec = VariableDeclaration(variable: Variable(name: "x"), type: VariableType(type: .integer))
490+
let compound = Compound(children: [Assignment(left: Variable(name: "x"), right: Number.integer(0)), While(statement: Assignment(left: Variable(name: "x"), right: BinaryOperation(left: Variable(name: "x"), operation: BinaryOperationType.plus, right: Number.integer(1))), condition: Condition(type: .lessThan, leftSide: Variable(name: "x"), rightSide: Number.integer(6))), FunctionCall(name: "writeln", actualParameters: [Variable(name: "x")]), NoOp()])
491+
let block = Block(declarations: [xDec], compound: compound)
492+
let node = Program(name: "Main", block: block)
493+
XCTAssertEqual(result, node)
494+
}
472495
}

PascalInterpreter/PascalInterpreterTests/XCTestCase+FatalError.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ func XCTAssertEqual(_ left: AST, _ right: AST) {
137137
case let (left as RepeatUntil, right as RepeatUntil):
138138
XCTAssertEqual(left.condition, right.condition)
139139
XCTAssertEqual(left.statement, right.statement)
140+
case let (left as While, right as While):
141+
XCTAssertEqual(left.condition, right.condition)
142+
XCTAssertEqual(left.statement, right.statement)
140143
case let (left as For, right as For):
141144
XCTAssertEqual(left.variable, right.variable)
142145
XCTAssertEqual(left.startValue, right.startValue)

0 commit comments

Comments
 (0)