/* * Copyright (c) 1999-2003, Gene Cooperman; Rights to copy and distribute * for non-commercial purposes only are freely granted, but only as * long as this copyright statement remains. No warranty is implied. */ import java.util.ArrayList; import java.io.*; /** * Read * http://java.sun.com/j2se/1.4.2/docs/api/java/io/StreamTokenizer.html * for a description of basic concepts. */ class SchemeReader extends StreamTokenizer { SchemeReader( InputStream in ) { this( new BufferedReader( new InputStreamReader( in ) ) ); } SchemeReader( Reader r ) { super(r); init(); } void init() { // Lower than '!' is whitespace by default. whitespaceChars(' ', ' '); whitespaceChars('\t', '\t'); whitespaceChars('\n', '\n'); whitespaceChars('\r', '\r'); wordChars( '!', '~' ); commentChar(';'); slashSlashComments( false ); // should be default anyway slashStarComments( false ); // should be default anyway quoteChar('"'); lowerCaseMode( true ); ordinaryChar('('); // token by itself, not word, et al. ordinaryChar(')'); // token by itself, not word, et al. ordinaryChar('\''); // token by itself, not word, et al. ordinaryChar('\\'); // token by itself, not word, et al. parseNumbers(); // If it works as a number, do it. // Problem for 3 char symbol: a\ b // 1abc is a word in Scheme; Does this do the same thing? } public int nextToken() throws IOException { int tokenType = super.nextToken(); // if ( ttype == '\' ) Get next character. return tokenType; // TT_NUMBER, nval // TT_WORD, sval // string, sval set, and ttype = '"' // single character token ('), ttype // TT_EOF // escape character (\) ??? } /** * @param void * @return SchemeObject or else #f if it saw only ")" */ public SchemeObject nextExpression( ) throws IOException { SchemeObject result = nextExpression2(); if (result == null) { System.err.println("Scheme: Unmatched parenthesis returned"); return Symbol.schemeFalse; } else return result; } SchemeObject make_list_from_sequence(ArrayList al) { SchemeObject expr = Symbol.schemeNil; for (int i = al.size() - 1; i >= 0; i--) expr = new Cons( (SchemeObject)al.get(i), expr ); return expr; } /** * @param void * @return SchemeObject or else null if it saw only ")" */ public SchemeObject nextExpression2() throws IOException { while( true ) { switch ( this.nextToken() ) { case ')': /* end of list */ return null; case '(': /* Read list */ ArrayList al = new ArrayList(); SchemeObject expr = null; while( (expr = nextExpression2()) != null ) al.add(expr); return make_list_from_sequence(al); case '\'': /* 'x => (quote x) */ return new Cons( SchemeInterpreter.obArray.get("quote"), new Cons( nextExpression(), Symbol.schemeNil ) ); case '"': /* "string" */ // Should have been SchemeString, if it were implemented return new Symbol(sval); case TT_WORD: // StreamTokenizer defines sval when nextToken() is called. return SchemeInterpreter.obArray.getOrAdd( this.sval ); case '-': //StreamTokenizer bug: - yields '-', not TT_WORD (cf. wordChars) return SchemeInterpreter.obArray.getOrAdd( "-" ); case TT_NUMBER: // Should distinguish betwene Fixnum and SchemeFloat, // if it were implemented. return new Fixnum( (int)this.nval ); case TT_EOL: System.exit(1); } } } }