// // Sreader.java : S 式の Reader クラス定義 // // This is a part of miolisp sourcefile // Copyright (C) 1998 Nishiyama, Naoki / Mio software lab. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // import java.io.* ; // S 式のリーダ class Sreader { static final int COMMENTCHAR = ';',DOTCHAR = '.', QUOTECHAR = '\'', ESCAPECHAR = '\\',STRTERMCHAR = '\"' , COMMACHAR = ',', ATCHAR = '@' , BQCHAR = '`' ; Reader r ; StreamTokenizer st ; Sreader(InputStream i) { this(new InputStreamReader(i)) ; } Sreader(Reader re) { r = re ; st = new StreamTokenizer(r) ; streset() ; } boolean ready() throws IOException { return r.ready() ; } void streset() { st.commentChar(COMMENTCHAR) ; // コメントはセミコロン st.eolIsSignificant(false) ; // 行の終りは単なる空白 st.slashStarComments(false) ; st.slashSlashComments(false) ; st.lowerCaseMode(false) ; st.quoteChar(STRTERMCHAR) ; st.ordinaryChar(QUOTECHAR) ; st.ordinaryChar(DOTCHAR) ; // '.' が 0.0 になるのを防ぐ st.wordChars(DOTCHAR,DOTCHAR) ; // '.' が 0.0 になるのを防ぐ st.wordChars('+','+') ; st.wordChars('*','*') ; st.wordChars('/','/') ; st.wordChars('=','=') ; st.wordChars(':',':') ; st.wordChars('&','&') ; // for &aux &rest st.wordChars('$','$') ; // st.wordChars(128,255) ; // } // 指定の入力から S 式を 1 つ読み込む Object read() throws IOException,SreaderException { Object res ; int ttype ; ttype = st.nextToken() ; switch(ttype) { case StreamTokenizer.TT_WORD: if (st.sval.charAt(0) == DOTCHAR) { throw new SreaderException("Badly placed dot.") ; } res = SAtom.getSAtom(st.sval) ; break ; case StreamTokenizer.TT_NUMBER: res = new Double(st.nval) ; break ; case '(': Object a,d ; try { a = read() ; } catch(SreaderException e) { // () の処理 if (!e.getMessage().equals(")")) throw e ; res = SAtom.nil ; break ; } d = readcdr() ; res = new Cons(a,d) ; break ; case ')': throw new SreaderException(")") ; case QUOTECHAR : res = new Cons(SAtom.quote,new Cons(read(),SAtom.nil)) ; break ; case STRTERMCHAR : res = st.sval ; break ; case COMMACHAR : if (st.nextToken() == ATCHAR) { // ,@ ? res = new Cons(SAtom.commaat,new Cons(read(),SAtom.nil)) ; } else { st.pushBack() ; res = new Cons(SAtom.comma,new Cons(read(),SAtom.nil)) ; } break ; case BQCHAR : res = new Cons(SAtom.bquote,new Cons(read(),SAtom.nil)) ; break ; case StreamTokenizer.TT_EOF: throw new SreaderException("Sexpr not ended at EOF") ; default : throw new SreaderException("Unknown char : "+ttype) ; } return res ; } // in から S 式を 1 つ読み込む Object readcdr() throws IOException,SreaderException { Object res ; int ttype ; ttype = st.nextToken() ; switch(ttype) { case StreamTokenizer.TT_WORD: if (st.sval.charAt(0) == DOTCHAR) { try { res = read() ; } catch(SreaderException e) { // () の処理 if (!e.getMessage().equals(")")) throw e ; res = SAtom.nil ; break ; } ttype = st.nextToken() ; // ')' の空読み if (ttype == ')') break ; throw new SreaderException(") expected after dot pair.") ; } else { res = new Cons(SAtom.getSAtom(st.sval),readcdr()) ; } break ; case StreamTokenizer.TT_NUMBER: res = new Cons(new Double(st.nval),readcdr()) ; break ; case '(': Object a,d ; try { a = read() ; } catch(SreaderException e) { // () の処理 if (!e.getMessage().equals(")")) throw e ; res = new Cons(SAtom.nil,readcdr()) ; break ; } d = readcdr() ; Cons c = new Cons(a,d) ; res = new Cons(c,readcdr()) ; break ; case ')': res = SAtom.nil ; break ; case QUOTECHAR : c = new Cons(SAtom.quote,new Cons(read(),SAtom.nil)) ; res = new Cons(c,readcdr()) ; break ; case STRTERMCHAR : res = new Cons(st.sval,readcdr()) ; break ; case COMMACHAR : if (st.nextToken() == ATCHAR) { // ,@ ? c = new Cons(SAtom.commaat,new Cons(read(),SAtom.nil)) ; } else { st.pushBack() ; c = new Cons(SAtom.comma,new Cons(read(),SAtom.nil)) ; } res = new Cons(c,readcdr()) ; break ; case BQCHAR : c = new Cons(SAtom.bquote,new Cons(read(),SAtom.nil)) ; res = new Cons(c,readcdr()) ; break ; case StreamTokenizer.TT_EOF: throw new SreaderException("Sexpr not ended at EOF") ; default : throw new SreaderException("Unknown char : "+ttype) ; } return res ; } }