부록 II
참고용으로, 우리가 만들었던 작은 스크립트가 jlox의 구문 트리 클래스를 자동으로 생성하기 위해 만들었던 코드를 여기에 소개합니다.
A2 . 1표현식
표현식은 "코드 표현"에서 소개된 첫 번째 구문 트리 노드입니다. 메인 Expr 클래스는 특정 표현식 타입을 디스패치하는 데 사용되는 방문자 인터페이스를 정의하며, 다른 표현식 서브클래스들을 중첩 클래스로 포함합니다.
새 파일 생성
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); }
A2 . 1 . 1할당 표현식
변수 할당은 "문장과 상태"에서 소개됩니다.
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; }
A2 . 1 . 2이항 표현식
이항 연산자는 "코드 표현"에서 소개됩니다.
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; }
A2 . 1 . 3호출 표현식
함수 호출 표현식은 "함수"에서 소개됩니다.
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; }
A2 . 1 . 4가져오기 표현식
속성 접근, 즉 "가져오기(get)" 표현식은 "클래스"에서 소개됩니다.
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; }
A2 . 1 . 5그룹화 표현식
괄호를 사용한 표현식 그룹화는 "코드 표현"에서 소개됩니다.
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; }
A2 . 1 . 6리터럴 표현식
리터럴 값 표현식은 "코드 표현"에서 소개됩니다.
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; }
A2 . 1 . 7논리 표현식
논리 연산자 and와 or는 "제어 흐름"에서 소개됩니다.
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; }
A2 . 1 . 8설정 표현식
속성 할당, 즉 "설정(set)" 표현식은 "클래스"에서 소개됩니다.
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; }
A2 . 1 . 9super 표현식
super 표현식은 "상속"에서 소개됩니다.
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; }
A2 . 1 . 10this 표현식
this 표현식은 "클래스"에서 소개됩니다.
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; }
A2 . 1 . 11단항 표현식
단항 연산자는 "코드 표현"에서 소개됩니다.
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; }
A2 . 1 . 12변수 표현식
변수 접근 표현식은 "문장과 상태"에서 소개됩니다.
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; }
A2 . 2문장
문장은 표현식과는 독립적인 두 번째 구문 트리 노드 계층을 형성합니다. 우리는 "문장과 상태"에서 처음 몇 가지를 추가했습니다.
새 파일 생성
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); }
A2 . 2 . 1블록 문장
지역 스코프를 정의하는 중괄호 블록 문장은 "문장과 상태"에서 소개됩니다.
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; }
A2 . 2 . 2클래스 문장
클래스 선언은 당연하게도 "클래스"에서 소개됩니다.
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; }
A2 . 2 . 3표현식 문장
표현식 문장은 "문장과 상태"에서 소개됩니다.
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; }
A2 . 2 . 4함수 문장
함수 선언은 예상했듯이 "함수"에서 소개됩니다.
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; }
A2 . 2 . 5if 문장
if 문장은 "제어 흐름"에서 소개됩니다.
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; }
A2 . 2 . 6print 문장
print 문장은 "문장과 상태"에서 소개됩니다.
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; }
A2 . 2 . 7return 문장
반환할 함수가 필요하므로, return 문장은 "함수"에서 소개됩니다.
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; }
A2 . 2 . 8변수 문장
변수 선언은 "문장과 상태"에서 소개됩니다.
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; }
A2 . 2 . 9while 문장
while 문장은 "제어 흐름"에서 소개됩니다.
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; }