박은종의 객체지향 설계를 위한 디자인패턴 with 자바
Interpreter Pattern
- 문법 규칙을 클래스로 표현
- 간단한 프로그램을 해석하기 위한 패턴
- 간단한 언어에 대한 해석기 패턴
- 각 문법에 대한 해석을 클래스로 표현
- 미니언어나 게임에서 사용하는 간단한 언어에 대한 문법 해석기
- 문법의 변경이나 확장이 쉽고
- 문법의 구현이 쉽다.
- 복잡한 문법은 사용할 수 없다.
package com.backend.bakckend.designpattern.interpreter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;
import java.util.Vector;
abstract class Node {
abstract void parse(Context context) throws ParseException;
}
class ProgramNode extends Node {
private Node commandListNode;
void parse(Context context) throws ParseException {
context.skipToken("program");
commandListNode = new CommandListNode();
commandListNode.parse(context);
}
public String toString() {
return "[program " + commandListNode + "]";
}
}
class CommandListNode extends Node{
private Vector list = new Vector();
void parse(Context context) throws ParseException {
while(true){
if(context.currentToken() == null){
throw new ParseException("Missing 'end'", 0);
}else if(context.currentToken().equals("end")){
context.skipToken("end");
break;
}else{
Node commandNode = new CommandNode();
commandNode.parse(context);
list.add(commandNode);
}
}
}
public String toString() {
return list.toString();
}
}
class CommandNode extends Node{
private Node node;
void parse(Context context) throws ParseException {
if(context.currentToken().equals("repeat")){
node = new RepeatCommandNode();
node.parse(context);
}else{
node = new PrimitiveCommandNode();
node.parse(context);
}
}
public String toString() {
return node.toString();
}
}
class RepeatCommandNode extends Node{
private int number;
private Node commandListNode;
void parse(Context context) throws ParseException {
context.skipToken("repeat");
number = context.currentNumber();
context.nextToken();
commandListNode = new CommandListNode();
commandListNode.parse(context);
}
public String toString() {
return "[repeat " + number + " " + commandListNode + "]";
}
}
class PrimitiveCommandNode extends Node{
private String name;
void parse(Context context) throws ParseException {
name = context.currentToken();
context.skipToken(name);
if(!name.equals("go") && !name.equals("right") && !name.equals("left")){
throw new ParseException(name + " is undefined", 0);
}
}
public String toString() {
return name;
}
}
class Context{
private StringTokenizer tokenizer;
private String currentToken;
public Context(String text){
tokenizer = new StringTokenizer(text);
nextToken();
}
public String nextToken(){
if(tokenizer.hasMoreTokens()){
currentToken = tokenizer.nextToken();
}else{
currentToken = null;
}
return currentToken;
}
public String currentToken(){
return currentToken;
}
public void skipToken(String token) throws ParseException {
if(!token.equals(currentToken)){
throw new ParseException("Warning: " + token + " is expected, but " + currentToken + " is found.", 0);
}
nextToken();
}
public int currentNumber() throws ParseException {
int number = 0;
try{
number = Integer.parseInt(currentToken);
}catch(NumberFormatException e){
throw new ParseException("Warning: " + e, 0);
}
return number;
}
}
class ParseException extends Exception{
public ParseException(String msg, int errorPos){
super(msg);
}
}
public class InterpreterTest {
public static void main(String[] args) {
try{
BufferedReader reader = new BufferedReader(new FileReader("program.txt"));
String text;
while((text = reader.readLine()) != null){
System.out.println("text = \"" + text + "\"");
Node node = new ProgramNode();
node.parse(new Context(text));
System.out.println("node = " + node);
}
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
package com.backend.bakckend.designpattern.interpreter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;
import java.util.Vector;
abstract class Node {
abstract void parse(Context context) throws ParseException;
}
class ProgramNode extends Node {
private Node commandListNode;
void parse(Context context) throws ParseException {
context.skipToken("program");
commandListNode = new CommandListNode();
commandListNode.parse(context);
}
public String toString() {
return "[program " + commandListNode + "]";
}
}
class CommandListNode extends Node{
private Vector list = new Vector();
void parse(Context context) throws ParseException {
while(true){
if(context.currentToken() == null){
throw new ParseException("Missing 'end'", 0);
}else if(context.currentToken().equals("end")){
context.skipToken("end");
break;
}else{
Node commandNode = new CommandNode();
commandNode.parse(context);
list.add(commandNode);
}
}
}
public String toString() {
return list.toString();
}
}
class CommandNode extends Node{
private Node node;
void parse(Context context) throws ParseException {
if(context.currentToken().equals("repeat")){
node = new RepeatCommandNode();
node.parse(context);
}else{
node = new PrimitiveCommandNode();
node.parse(context);
}
}
public String toString() {
return node.toString();
}
}
class RepeatCommandNode extends Node{
private int number;
private Node commandListNode;
void parse(Context context) throws ParseException {
context.skipToken("repeat");
number = context.currentNumber();
context.nextToken();
commandListNode = new CommandListNode();
commandListNode.parse(context);
}
public String toString() {
return "[repeat " + number + " " + commandListNode + "]";
}
}
class PrimitiveCommandNode extends Node{
private String name;
void parse(Context context) throws ParseException {
name = context.currentToken();
context.skipToken(name);
if(!name.equals("go") && !name.equals("right") && !name.equals("left")){
throw new ParseException(name + " is undefined", 0);
}
}
public String toString() {
return name;
}
}
class Context{
private StringTokenizer tokenizer;
private String currentToken;
public Context(String text){
tokenizer = new StringTokenizer(text);
nextToken();
}
public String nextToken(){
if(tokenizer.hasMoreTokens()){
currentToken = tokenizer.nextToken();
}else{
currentToken = null;
}
return currentToken;
}
public String currentToken(){
return currentToken;
}
public void skipToken(String token) throws ParseException {
if(!token.equals(currentToken)){
throw new ParseException("Warning: " + token + " is expected, but " + currentToken + " is found.", 0);
}
nextToken();
}
public int currentNumber() throws ParseException {
int number = 0;
try{
number = Integer.parseInt(currentToken);
}catch(NumberFormatException e){
throw new ParseException("Warning: " + e, 0);
}
return number;
}
}
class ParseException extends Exception{
public ParseException(String msg, int errorPos){
super(msg);
}
}
public class InterpreterTest {
public static void main(String[] args) {
try{
BufferedReader reader = new BufferedReader(new FileReader("program.txt"));
String text;
while((text = reader.readLine()) != null){
System.out.println("text = \"" + text + "\"");
Node node = new ProgramNode();
node.parse(new Context(text));
System.out.println("node = " + node);
}
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
LIST
'4차산업혁명의 일꾼 > Java&Spring웹개발과 서버 컴퓨터' 카테고리의 다른 글
자바개발자의 툴 이클립스에서 인텔리제이 비교 (0) | 2023.03.14 |
---|---|
스프링의 정석 : 남궁성과 끝까지 간다 1 : 스프링MVC , SpringMVC (0) | 2023.03.13 |
디자인패턴 - Command Pattern (0) | 2023.03.12 |
디자인 패턴 with 자바 - 낭비를 없애기(Flyweight, Proxy) (0) | 2023.03.09 |
스프링 부트의 정석 : 이번에도 남궁성과 끝까지 간다 1 (0) | 2023.03.06 |