A2

부록 II

참고용으로, 우리가 만들었던 작은 스크립트가 jlox의 구문 트리 클래스를 자동으로 생성하기 위해 만들었던 코드를 여기에 소개합니다.

A2 . 1표현식

표현식은 "코드 표현"에서 소개된 첫 번째 구문 트리 노드입니다. 메인 Expr 클래스는 특정 표현식 타입을 디스패치하는 데 사용되는 방문자 인터페이스를 정의하며, 다른 표현식 서브클래스들을 중첩 클래스로 포함합니다.

lox/Expr.java
새 파일 생성
package com.craftinginterpreters.lox;

import java.util.List;

abstract class Expr {
  interface Visitor<R> {
    R visitAssignExpr(Assign expr);
    R visitBinaryExpr(Binary expr);
    R visitCallExpr(Call expr);
    R visitGetExpr(Get expr);
    R visitGroupingExpr(Grouping expr);
    R visitLiteralExpr(Literal expr);
    R visitLogicalExpr(Logical expr);
    R visitSetExpr(Set expr);
    R visitSuperExpr(Super expr);
    R visitThisExpr(This expr);
    R visitVariableExpr(Variable expr);
  }

  // 여기에 중첩된 Expr 클래스들이 옵니다...

  abstract <R> R accept(Visitor<R> visitor);
}
lox/Expr.java, 새 파일 생성

A2 . 1 . 1할당 표현식

변수 할당은 "문장과 상태"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Assign extends Expr {
    Assign(Token name, Expr value) {
      this.name = name;
      this.value = value;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitAssignExpr(this);
    }

    final Token name;
    final Expr value;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 2이항 표현식

이항 연산자는 "코드 표현"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Binary extends Expr {
    Binary(Expr left, Token operator, Expr right) {
      this.left = left;
      this.operator = operator;
      this.right = right;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitBinaryExpr(this);
    }

    final Expr left;
    final Token operator;
    final Expr right;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 3호출 표현식

함수 호출 표현식은 "함수"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Call extends Expr {
    Call(Expr callee, Token paren, List<Expr> arguments) {
      this.callee = callee;
      this.paren = paren;
      this.arguments = arguments;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitCallExpr(this);
    }

    final Expr callee;
    final Token paren;
    final List<Expr> arguments;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 4가져오기 표현식

속성 접근, 즉 "가져오기(get)" 표현식은 "클래스"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Get extends Expr {
    Get(Expr object, Token name) {
      this.object = object;
      this.name = name;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitGetExpr(this);
    }

    final Expr object;
    final Token name;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 5그룹화 표현식

괄호를 사용한 표현식 그룹화는 "코드 표현"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Grouping extends Expr {
    Grouping(Expr expression) {
      this.expression = expression;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitGroupingExpr(this);
    }

    final Expr expression;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 6리터럴 표현식

리터럴 값 표현식은 "코드 표현"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Literal extends Expr {
    Literal(Object value) {
      this.value = value;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitLiteralExpr(this);
    }

    final Object value;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 7논리 표현식

논리 연산자 andor는 "제어 흐름"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Logical extends Expr {
    Logical(Expr left, Token operator, Expr right) {
      this.left = left;
      this.operator = operator;
      this.right = right;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitLogicalExpr(this);
    }

    final Expr left;
    final Token operator;
    final Expr right;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 8설정 표현식

속성 할당, 즉 "설정(set)" 표현식은 "클래스"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Set extends Expr {
    Set(Expr object, Token name, Expr value) {
      this.object = object;
      this.name = name;
      this.value = value;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitSetExpr(this);
    }

    final Expr object;
    final Token name;
    final Expr value;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 9super 표현식

super 표현식은 "상속"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Super extends Expr {
    Super(Token keyword, Token method) {
      this.keyword = keyword;
      this.method = method;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitSuperExpr(this);
    }

    final Token keyword;
    final Token method;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 10this 표현식

this 표현식은 "클래스"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class This extends Expr {
    This(Token keyword) {
      this.keyword = keyword;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitThisExpr(this);
    }

    final Token keyword;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 11단항 표현식

단항 연산자는 "코드 표현"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Unary extends Expr {
    Unary(Token operator, Expr right) {
      this.operator = operator;
      this.right = right;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitUnaryExpr(this);
    }

    final Token operator;
    final Expr right;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 1 . 12변수 표현식

변수 접근 표현식은 "문장과 상태"에서 소개됩니다.

lox/Expr.java
Expr 클래스 내부에 중첩
  static class Variable extends Expr {
    Variable(Token name) {
      this.name = name;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitVariableExpr(this);
    }

    final Token name;
  }
lox/Expr.java, Expr 클래스 내부에 중첩

A2 . 2문장

문장은 표현식과는 독립적인 두 번째 구문 트리 노드 계층을 형성합니다. 우리는 "문장과 상태"에서 처음 몇 가지를 추가했습니다.

lox/Stmt.java
새 파일 생성
package com.craftinginterpreters.lox;

import java.util.List;

abstract class Stmt {
  interface Visitor<R> {
    R visitBlockStmt(Block stmt);
    R visitClassStmt(Class stmt);
    R visitExpressionStmt(Expression stmt);
    R visitFunctionStmt(Function stmt);
    R visitIfStmt(If stmt);
    R visitPrintStmt(Print stmt);
    R visitReturnStmt(Return stmt);
    R visitVarStmt(Var stmt);
    R visitWhileStmt(While stmt);
  }

  // 여기에 중첩된 Stmt 클래스들이 옵니다...

  abstract <R> R accept(Visitor<R> visitor);
}
lox/Stmt.java, 새 파일 생성

A2 . 2 . 1블록 문장

지역 스코프를 정의하는 중괄호 블록 문장은 "문장과 상태"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Block extends Stmt {
    Block(List<Stmt> statements) {
      this.statements = statements;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitBlockStmt(this);
    }

    final List<Stmt> statements;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 2클래스 문장

클래스 선언은 당연하게도 "클래스"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Class extends Stmt {
    Class(Token name,
          Expr.Variable superclass,
          List<Stmt.Function> methods) {
      this.name = name;
      this.superclass = superclass;
      this.methods = methods;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitClassStmt(this);
    }

    final Token name;
    final Expr.Variable superclass;
    final List<Stmt.Function> methods;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 3표현식 문장

표현식 문장은 "문장과 상태"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Expression extends Stmt {
    Expression(Expr expression) {
      this.expression = expression;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitExpressionStmt(this);
    }

    final Expr expression;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 4함수 문장

함수 선언은 예상했듯이 "함수"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Function extends Stmt {
    Function(Token name, List<Token> params, List<Stmt> body) {
      this.name = name;
      this.params = params;
      this.body = body;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitFunctionStmt(this);
    }

    final Token name;
    final List<Token> params;
    final List<Stmt> body;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 5if 문장

if 문장은 "제어 흐름"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class If extends Stmt {
    If(Expr condition, Stmt thenBranch, Stmt elseBranch) {
      this.condition = condition;
      this.thenBranch = thenBranch;
      this.elseBranch = elseBranch;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitIfStmt(this);
    }

    final Expr condition;
    final Stmt thenBranch;
    final Stmt elseBranch;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 6print 문장

print 문장은 "문장과 상태"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Print extends Stmt {
    Print(Expr expression) {
      this.expression = expression;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitPrintStmt(this);
    }

    final Expr expression;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 7return 문장

반환할 함수가 필요하므로, return 문장은 "함수"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Return extends Stmt {
    Return(Token keyword, Expr value) {
      this.keyword = keyword;
      this.value = value;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitReturnStmt(this);
    }

    final Token keyword;
    final Expr value;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 8변수 문장

변수 선언은 "문장과 상태"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class Var extends Stmt {
    Var(Token name, Expr initializer) {
      this.name = name;
      this.initializer = initializer;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitVarStmt(this);
    }

    final Token name;
    final Expr initializer;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩

A2 . 2 . 9while 문장

while 문장은 "제어 흐름"에서 소개됩니다.

lox/Stmt.java
Stmt 클래스 내부에 중첩
  static class While extends Stmt {
    While(Expr condition, Stmt body) {
      this.condition = condition;
      this.body = body;
    }

    @Override
    <R> R accept(Visitor<R> visitor) {
      return visitor.visitWhileStmt(this);
    }

    final Expr condition;
    final Stmt body;
  }
lox/Stmt.java, Stmt 클래스 내부에 중첩