Skip to content

Commit

Permalink
Parser & Interpreter now parse and execiute statement
Browse files Browse the repository at this point in the history
  • Loading branch information
theSalted committed Jun 26, 2024
1 parent 0384e12 commit 8763317
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 18 deletions.
5 changes: 2 additions & 3 deletions Sources/Lox/Definitions/Statement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public protocol Statement {
public protocol StatementVisitor {
associatedtype StatementVisitorReturn

func visit(_ expr: Expr) -> StatementVisitorReturn
func visit(_ expr: Print) -> StatementVisitorReturn
func visit(_ stmt: Expr) -> StatementVisitorReturn
func visit(_ stmt: Print) -> StatementVisitorReturn
}

public struct Expr: Statement {
Expand All @@ -40,4 +40,3 @@ public struct Print: Statement {
return visitor.visit(self)
}
}

52 changes: 51 additions & 1 deletion Sources/Lox/Interpreter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,20 @@

import OSLog

public final class Interpreter: ExpressionVisitor {
public final class Interpreter: StatementVisitor, ExpressionVisitor {

func intercept(_ statements: Array<Statement>) {
for statement in statements {
switch execute(stmt: statement) {

case .success(_), .none:
break
case .failure(let error):
return Lox.reportError(error)
}
}
}

func intercept(_ expr: Expression) {
switch evaluate(expr) {
case .success(let result):
Expand All @@ -19,6 +32,42 @@ public final class Interpreter: ExpressionVisitor {
}
}

func execute(stmt: Statement) -> Value? {
switch stmt.accept(visitor: self) {

case .none, .success(_):
return nil
case .failure(let error):
return .failure(error)
}
}

// MARK: Statements
public func visit(_ stmt: Expr) -> Value? {
switch evaluate(stmt.expression) {

case .success(_), .none:
return nil
case .failure(let error):
return .failure(error)
}
}

public func visit(_ stmt: Print) -> Value? {
switch evaluate(stmt.expression) {

case .success(let value):
print(toString(value))
return nil
case .none:
print(toString(nil))
return nil
case .failure(let error):
return .failure(error)
}
}

// MARK: Expressions
public func visit(_ expr: Binary) -> Value? {
// MARK: Preparing operands, and operator
let `operator` = expr.operator
Expand Down Expand Up @@ -129,6 +178,7 @@ public final class Interpreter: ExpressionVisitor {

public typealias Value = Result<Any, InterpreterError>
public typealias ExpressionVisitorReturn = Value?
public typealias StatementVisitorReturn = Value?
}

extension Interpreter {
Expand Down
10 changes: 3 additions & 7 deletions Sources/Lox/Lox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,11 @@ public struct Lox {
}

let parser = Parser(tokens: tokens)
guard let expression = parser.parse() else {
if (!hadError) {
print("Parser exited unexpectedly")
}
return
}
let statements = parser.parse()

if (hadError) { return }

interpreter.intercept(expression)
interpreter.intercept(statements)
}

/// Runs the interpreter on the given code string.
Expand Down Expand Up @@ -91,6 +86,7 @@ public extension Lox {
} else {
reportError(message, at: " at \(token.lexeme)", on: token.line)
}
hadError = true
}

static func reportError(_ interpreterError: InterpreterError) {
Expand Down
42 changes: 38 additions & 4 deletions Sources/Lox/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,49 @@ public class Parser {
self.tokens = tokens
}

func parse() -> Expression? {
func parse() -> Array<Statement> {
var statements = Array<Statement>()
while !reachedEOF() {
if let statement = try? statement() {
statements.append(statement)
} else {
synchronize()
}
}
return statements
}

// MARK: Statements
private func statement() throws -> Statement {
if (match(.print)) { return try printStatement() }
return try expressionStatement()
}

private func expressionStatement() throws -> Statement {
let expression = try expression()

do {
return try expression()
try consume(.semicolon)
} catch {
return nil
throw reportError("Expect ';' after value", token: latestToken)
}

return Expr(expression: expression)
}

private func printStatement() throws -> Statement {
let value = try expression()
do {
try consume(.semicolon)
} catch {
throw reportError("Expect ';' after value", token: latestToken)
}

return Print(expression: value)
}


// MARK: Expressions
private func expression() throws -> Expression {
return try equality()
}
Expand Down Expand Up @@ -62,7 +97,6 @@ public class Parser {

return try primary()
}


private func primary() throws -> Expression {
if match(.false) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

{
"baseName": "Expression",
"baseAcronym": "expr",
"types": [
{
"name": "Binary",
Expand Down
1 change: 1 addition & 0 deletions Sources/SyntaxDefinitionGenerator/Resources/statement.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

{
"baseName": "Statement",
"baseAcronym": "stmt",
"types": [
{
"name": "Expr",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ struct SyntaxDefinitionGenerator {
let isPublic: Bool

/// Initializes a new generator.
init(_ tree: Definition, path outputDirectory: URL? = nil, isPublic: Bool = true) {
init(_ definition: Definition, path outputDirectory: URL? = nil, isPublic: Bool = true) {
self.outputDirectory = outputDirectory
self.definition = tree
self.definition = definition
self.isPublic = isPublic
}

Expand Down Expand Up @@ -119,7 +119,7 @@ struct SyntaxDefinitionGenerator {
printer.emptyLine()

for type in definition.types {
printer.writeLine("func visit(_ expr: \(type.name)) -> \(returnName)")
printer.writeLine("func visit(_ \((definition.baseAcronym ?? definition.baseName).lowercased()): \(type.name)) -> \(returnName)")
}

printer.detent()
Expand All @@ -146,6 +146,7 @@ struct SyntaxDefinitionGenerator {
/// Represents an abstract syntax tree.
struct Definition: Codable {
let baseName: String
let baseAcronym: String?
let types: [TypeDefinition]
}

Expand Down

0 comments on commit 8763317

Please sign in to comment.