1.개요
제한된 프로그래밍 언어에 대한 간단한 인터프리터를 만들어 보기로 한다. 언어는 변수 선언, 반복문, 조건문, 함수 등 다양한 구성 요소를 갖지만 여기서는 전체적으로 인터프리터의 작동 원리를 이해하는데 초점을 맞추므로 간단한 배정문에 국한해서 인터프리터를 만들어 본다.
2.동작
public double parseStatement()
Statement는 오른쪽 Expression을 파싱한 결과를 왼쪽 식별자에게 배정하고 그 결과를 반환합니다. 배정은 TreeMap의 put 메소드 사용하여 심볼 테이블에 저장합니다. 만약 ‘;’로 끝나지 않는다면 오류메시지를 출력합니다.
public double parseExpression()
더하기‘+’와 빼기‘-’의 역할을 배정합니다.
public double parseTerm()
곱하기‘*’와 나누기‘/’의 역할을 배정합니다.
public double parseFactor()
Factor는 Identifier나, Number나, 왼쪽 괄호 다음에 Expreesion이 오고 다음에 오른쪽 괄호가 오는 경우, 또는 마이너스 Factor의 4가지 경우를 파싱하여 그 결과를 반환합니다. 만약 없는 Variable이 들어온다면 오류메시지를 출력합니다.
3.코드
import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Map;
import java.util.TreeMap;
public class TestInterpreter {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
Interpreter itp = new Interpreter(in);
double result;
while (true) {
in.nextToken();
if (in.ttype == '#')
break;
in.pushBack();
try {
result = itp.parseStatement();
System.out.println("=> " + result);
} catch (SyntaxError e) {
System.out.println("\n" + e.getMessage());
System.exit(1);
}
}
itp.printSymbolTable();
}
}
class Interpreter {
private Map<String, Double> st;
private StreamTokenizer in;
public Interpreter(StreamTokenizer in) throws IOException {
this.in = in;
st = new TreeMap<String, Double>();
in.ordinaryChar('/');
in.ordinaryChar('-');
}
public void printSymbolTable() {
for (Map.Entry<String, Double> entry : st.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
public double parseStatement() throws IOException, SyntaxError {
String Variable = "";
double result = 0;
while (true){
in.nextToken();
switch (in.ttype){
case '=':
result = parseExpression();
in.nextToken();
if(in.ttype != ';') throw new SyntaxError("wrong statement end symbol!");
st.put(Variable, result);
return result;
default:
Variable += in.sval;
}
}
}
public double parseExpression() throws IOException, SyntaxError {
double result = parseTerm();
while (true) {
in.nextToken();
switch (in.ttype) {
case '+':
result += parseTerm();
break;
case '-':
result -= parseTerm();
break;
default:
in.pushBack();
return result;
}
}
}
public double parseTerm() throws IOException, SyntaxError {
double result = parseFactor();
while (true){
in.nextToken();
switch (in.ttype){
case '*':
result *= parseFactor();
break;
case '/':
result /= parseFactor();
break;
default:
in.pushBack();
return result;
}
}
}
public double parseFactor() throws IOException, SyntaxError {
double result ;
while (true){
in.nextToken();
switch (in.ttype){
case '(':
result = parseExpression();
in.nextToken();
if(in.ttype != ')') throw new SyntaxError();
return result;
case '-':
result = parseFactor()*(-1);
return result;
default:
if(in.sval == null) return in.nval;
else if(st.get(in.sval) != null) return st.get(in.sval);
else{
throw new SyntaxError("Unkown variable!");
}
}
}
}
}
class SyntaxError extends Exception {
public SyntaxError() {
super("Error in Statement");
}
public SyntaxError(String msg) {
super(msg);
}
}
4.결과
'자바 > 자료구조' 카테고리의 다른 글
[자바][자료구조] 이중연결자 Iterator (0) | 2020.04.03 |
---|---|
[자바][자료구조] 이진탐색트리 (0) | 2020.04.03 |
[자바][자료구조] DoublyLinked List 이중연결 리스트 삽입 삭제 탐색 (0) | 2020.03.31 |
댓글