스크립트 문자열 파싱

앞서 흐름제어문 전처리 단계가 완성되었고 스크립트에는 이제 함수호출문만이 남게되었다. 이제는 스크립트 문자열로부터 함수호출문을 파싱하는 로직이 필요했다. 그래서 이를 해석 모듈에서 구현하고 있었는데, 문득 이 작업을 전처리에서 다 해버리면 더 깔끔하겠다는 생각이 들었다.

 

파싱 작업

스크립트를 파싱하는 작업은 두 단계로 이뤄져있다.

  1. 스크립트를 각 함수호출문 별로 분리
  2. 함수호출문을 함수와 인수로 분리

첫번째 단계를 통해 하나의 스크립트 문자열을 함수호출문 문자열 리스트로 바꾸고, 두번째 단계를 통해 리스트의 각 항목마다 함수와 인수 정보를 획득해내 해석 단계에서 확인하기 편한 구조로 만든다.

 

스크립트 -> 함수호출문 리스트

DSL 문법체계에서 함수호출문은 세미콜론을 구분자 삼아 분리한다고 했다. 이 단계의 구현은 복잡하지 않다. 리스트를 생성한 뒤 문자열 버퍼를 적절히 활용해 추출해내면 된다.

 

함수호출문 -> 함수, 인수

함수호출문은 '함수이름(인수...)'와 같은 형태이다. 구조를 자세히 설명해보자면, 먼저 함수의 이름이 있고 그 뒤 괄호쌍 내부에 0개 이상의 인수가 존재하는 문자열이라고 할 수 있다. 이 문자열을 적절히 파싱해두면, 해석 단계에서 함수와 인수 정보를 쉽게 알 수 있다.

 

함수호출문 파싱 정보 클래스

public class Block {
    private final String method;
    private final List<Block> argBlocks;
}

함수호출문 파싱 정보를 담을 클래스이다. 함수호출문은 사실상 블록 인터페이스에서의 블록과 일대일 대응이어서 이름을 Block으로 정했다. method에는 함수의 이름이, argBlocks에는 인수 리스트가 담긴다. 그리고 앞서 인수에 함수호출문이 담길 수 있다고 했으니 인수의 타입 또한 Block이 된다.

 

인수가 상수의 경우

함수를 호출할 때, 상수 또한 당연히 인수로 전달할 수 있어야 한다. 그런데 Block 클래스를 보면 마땅히 상수와 관련된 필드가 없다. 그 이유는 method에 상수 값을 담아내도록 했기 때문이다. method 필드는 해석 과정에서 그 값의 상수 여부를 판단하게 된다.

 

넘어가며

전처리 과정은 이걸로 모두 끝이다. 파싱 작업을 통해 스크립트(String)를 함수호출문 목록(List<String>)으로 만들었고, 그것을 다시 파싱된 함수호출문 목록(List<Block>)으로 만들었다. 다음은 전처리가 완료된 스크립트를 해석하면서, 실행으로 넘어가기까지의 과정을 설명해보겠다.

+ Recent posts