티스토리 뷰

SW

[JAVA] StreamTokenizer 를 이용한 파서(Parser)

I like simple code 2020. 4. 25. 13:57
728x90
<prgm>a<stmt>
<stmt>a id = <expr>;
| '{'{<stmt>}'}'
| if'('<expr>')' then <stmt> [else <stmt>]
| while '('<expr>')' <stmt>
| read id;
| print <expr>;
<expr> a <bexp>

 

위처럼 태그가 포함된 문자열 또는 문서가 있을 때 저 문자들을 태그와 특수문자 그리고 문자열들을 구분해서 파싱을 해보자. 정확하게 어떤 결과가 나와야 하는지는 모르고 어떤 의도의 문제(혹시 컴파일러의 문법 파싱인가 유추...)인지도 솔직히 잘 모르겠으나 StreamTokenizer 를 활용을 한다면 필자는 이렇게 파싱을 해보았다. 

StreamTokenizer 는 자바(java.io)에 포함된 파싱을 도와주는 클래스 이다.

 

import java.io.StreamTokenizer;

 

위 클래스를 포함 시켜서 사용 한다.

 

아래는 저 문자열들이 포함된 텍스트 파일을 읽어와서 종류별로 파싱(문자열을 잘라내서)해 화면에 출력 해주는 코드이다. 태그 말고 나머지는 그냥 StreamTokenizer 에서

TT_WORD(문자열)

TT_NUMBER(숫자)

ttype의 값(특수문자 아스키코드값) 으로 구분이 가능 하다.

태그 같은 경우는 <부분도 특수 문자로 포함 되기 때문에  < 태그시작 표시 (아스키코드 60)가 나오면

nextToken()으로 다음 문자열을 얻고 한번더 nextToken()으로 > 태그 닫기 까지 받고 하나의 문자열로 만들어 태그를 구분 했다. 파싱을 해서 리스트에 담긴 데이터들은 가공이 가능 하다고 할 수 있다.

조금 더 효율적인 코드로 작성 할 수 있을 것이라고 본다. 필자는 여기까지...

 

parser.txt
0.00MB

 

parser.txt 파일을 읽어 와서 출력 결과

더보기
hello world
===== 태그 =====
<prgm>
<stmt>
<stmt>
<expr>
<stmt>
<expr>
<stmt>
<stmt>
<expr>
<stmt>
<expr>
<expr>
<bexp>
================
==== 문자열 ====
a
a
id
if
then
else
while
read
id
print
a
한글도
문자열로
구분이
됩니다
================
=== 특수문자 ===
=
;
|
'
{
}
'
|
'
'
[
]
|
'
'
|
;
|
;
================
===== 숫자 =====
================

 

MainClass.java  소스

더보기
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class MainClass {
    public static void main(String[] args) throws IOException{
        System.out.println("hello world");
        BufferedReader bufReader = new BufferedReader(new FileReader("parser.txt"));
        MyParser myParser = MyTokenizer.getStreamToken(bufReader);
        bufReader.close();

        // 잘 파싱이 되었는지 확인
        System.out.println("===== 태그 =====");
        MyTokenizer.getTagParseInfo(myParser);
        System.out.println("================");
        System.out.println("==== 문자열 ====");
        MyTokenizer.getStrParseInfo(myParser);
        System.out.println("================");
        System.out.println("=== 특수문자 ===");
        MyTokenizer.getCharParseInfo(myParser);
        System.out.println("================");
        System.out.println("===== 숫자 =====");
        MyTokenizer.getNumParseInfo(myParser);
        System.out.println("================");
    }

}

 

MyParse.java 소스

더보기
import java.util.ArrayList;

public class MyParser {
    private ArrayList<String> tagList;  // 태그
    private ArrayList<String> strList;  // 문자열
    private ArrayList<String> charList; // 특수문자
    private ArrayList<Double> numList;  // 숫자
    
    public MyParser() {
        tagList = new ArrayList<String>();
        strList = new ArrayList<String>();
        charList = new ArrayList<String>();
        numList = new ArrayList<Double>();
    }

    public ArrayList<String> getTagList() {
        return this.tagList;
    }

    public void setTagList(ArrayList<String> tagList) {
        this.tagList = tagList;
    }

    public void addTagList(String tag) {
        this.tagList.add(tag);
    }

    public ArrayList<String> getStrList() {
        return this.strList;
    }

    public void setStrList(ArrayList<String> strList) {
        this.strList = strList;
    }

    public void addStrList(String str) {
        this.strList.add(str);
    }

    public ArrayList<String> getCharList() {
        return this.charList;
    }

    public void setCharList(ArrayList<String> charList) {
        this.charList = charList;
    }

    public void addCharList(String ch) {
        this.charList.add(ch);
    }

    public ArrayList<Double> getNumList() {
        return this.numList;
    }

    public void setNumList(ArrayList<Double> numList) {
        this.numList = numList;
    }

    public void addNumList(double num) {
        this.numList.add(num);
    }
}

 

MyTokenizer.java 소스

더보기
import java.io.IOException;
import java.io.Reader;
import java.io.StreamTokenizer;

public class MyTokenizer {
    public static MyParser getStreamToken(Reader reader) throws IOException {
        StreamTokenizer streamTokenizer = new StreamTokenizer(reader);
        MyParser myParser = new MyParser();
        while (streamTokenizer.nextToken() != StreamTokenizer.TT_EOF) {
            if (streamTokenizer.ttype == StreamTokenizer.TT_WORD) {
                myParser.addStrList(streamTokenizer.sval);
                // System.out.println("문자열 : " + streamTokenizer.sval);
            } else if (streamTokenizer.ttype == StreamTokenizer.TT_NUMBER) {
                // System.out.println("숫자 : " + streamTokenizer.nval);
                myParser.addNumList(streamTokenizer.nval);
            } else if (streamTokenizer.ttype == 60){   // 60 은 아스크 코드에서 <
                // System.out.print("태그 : ");
                String tag = Character.toString((char)streamTokenizer.ttype);
                streamTokenizer.nextToken();
                tag += streamTokenizer.sval;
                streamTokenizer.nextToken();
                tag += Character.toString((char)streamTokenizer.ttype);
                myParser.addTagList(tag);
                // System.out.println(tag);
            } else {
                // System.out.println("특수문자 : " + (char)streamTokenizer.ttype);
                myParser.addCharList(Character.toString((char)streamTokenizer.ttype));
            }
        }
        return myParser;
    }

    // 태그
    public static void getTagParseInfo(MyParser myParser) {
        for (String s : myParser.getTagList()) {
            System.out.println(s);
        }
    }
    // 문자열
    public static void getStrParseInfo(MyParser myParser) {
        for (String s : myParser.getStrList()) {
            System.out.println(s);
        }
    }
    // 특수문자
    public static void getCharParseInfo(MyParser myParser) {
        for (String s : myParser.getCharList()) {
            System.out.println(s);
        }
    }   
    // 숫자
    public static void getNumParseInfo(MyParser myParser) {
        for (double s : myParser.getNumList()) {
            System.out.println(s);
        }
    }
}
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함