package io; import java.lang.*; import java.io.* ; /** Allows moving the position-pointer back and re-reading symbols provided they are within the buffer. Possible initialization with a specified size for the buffer ? Reading anything positions pointer at the first character after the returned string/character/integer. Contains Delimiter-list where user can put single delimiters or pairs of matching characters/strings to be treated as parantheses. Reading a token means then reading either one of delimiters or string between two such. SPACE (' ') is by default a (single) delimiter. */ public class TokenInputBuffer extends BufferedInputStream { /* initialization with in.size makes sense ? */ private int LinijkaNo=1; /** character for end-of-file */ public char EOF= ((char)(-1)); private boolean endsLine(int c) { return ((char)c=='\n' || (char)c=='\r' || c==-1); } private boolean endsLine(char c) { return (c=='\n' || c=='\r' || c== ((char)(-1))); } private void ifNewLine(int c) { if (endsLine(c)) LinijkaNo=LinijkaNo+1; } private void ifNewLine(char c) { if (endsLine(c)) LinijkaNo=LinijkaNo+1; } /** @param in put this TokenInputBuffer as a "filter" on in @see BufferedInputStream */ public TokenInputBuffer(InputStream in) { super(in); } /** @param in put this TokenInputBuffer as a "filter" on in @param size with specified buffer size @see BufferedInputStream */ public TokenInputBuffer(InputStream in, int size) { super(in,size); } /** move position-pointer x characters back */ public void unread(int x) { int k,c=0,z,r; if (x>pos) {z= pos; pos= 0;} else {z=x; pos= pos-x;} for (k=0; k< x; k++) try{ r= read(); if (endsLine(r)) c=c+1; } catch(IOException e){} LinijkaNo= LinijkaNo-c; if (x>pos) pos = 0; else pos= pos-x; } /** move position-pointer 1 character back */ public void unread() { unread(1); } /** read next character */ public final char tegn() { char c='0'; int ch=0; try{ ch= read(); c= (char)ch; ifNewLine(ch); } catch(IOException e){} return c; } /** read next non-SPACE character (skipping over ' ') */ public final char tegnNB() { char c='0'; int ch=0; try{ ch= read(); c= (char)ch; ifNewLine(ch); while (Character.isWhitespace(c) || c==' ') {ch= read(); c=(char)ch; ifNewLine(ch); } } catch(IOException e){} return c; } /** return next NonFormatting character (not SPACE, \n, \r, \t) */ public char tegnNF() { char c= tegnNB(); while (!EOF() && (endsLine(c) || c=='\t')) c=tegnNB(); return c; } /** read next integer: skip initial non-digits */ public final int htall() { int r=0, ch, s=0; try{ ch= read()-48; ifNewLine(ch+48); while (ch<0 || ch>9) {s=ch; ch= read()-48; ifNewLine(ch+48);} r= ch; ch= read()-48; ifNewLine(ch+48); while (ch >= 0 && ch <= 9) {r= (r*10)+ch; ch= read()-48; ifNewLine(ch+48); } unread(); } catch(IOException e){} s= s+48; if ((char)s == '-') {r= -r;} return r; } /** read next boolean - one character; false iff it is 'n', 'N', '0' or '-' */ public final boolean bool() { char c= tegn(); if ( c=='n' || c=='N' || c=='0' || c=='-') return false; else return true; } /** read next word - non-SPACE characters between SPACEs */ public final String ord() { char c= tegn(); String s= new String(""); while (c == ' ') { c= tegn(); } while (c != ' ') {s= s+c; c= tegn();} unread(); return s; } /** read word starting with a letter and containing only letters or digits; */ /* this one re-positions the pointer one step back after discovering a non-letterOrDigit terminating the word, so that the next 'read' will return the first character after the read word */ public final String ordLD() { int ch, i; char c; String s= new String(""); c= tegn(); i=1; while (!Character.isLetter(c)) { c= tegn(); i= i+1;} while (Character.isLetterOrDigit(c)) {s=s+c; c= tegn(); i=i+1;} unread(); return s; } /** returns the line number (in the source Stream) of the last read character */ public int LineNo() { return LinijkaNo; } /** returns true iff the next character is EOF; if it isn't re-positions the pointer to enable a new reading of this character and returns false */ public boolean EOF() { char c= tegn(); boolean res; if (c == EOF) { res= true;} else { unread(); res= false;} return res; } /** check if next NonFormatting character is EOF; if it isn't, reposition the pointer, so that this character will be next to read */ public boolean EOFnf() { char c= tegnNF(); if (c == EOF) return true; else {unread(); return false; } } /** check if next non-SPACE character is EOF; if it isn't, reposition the pointer, so that this character will be next to read */ public boolean EOFnb() { char c= tegnNB(); if (c == EOF) return true; else {unread(); return false; } } /* the following part is a Tokenizer; allowing reading words up to or between specified delimiters as well as specifying pairs of paranthetical delimiters L and R which should match; the default Delimiter is " ", and one need some char Delimiters but otherwise Delimiters may be arbitrary String */ /* Delimiters are Pairs -- a single Delimiter has fst().equals(snd()) */ private class Pair { private Object a, b ; Pair(Object f, Object s) { a= f; b= s; } Object fst() { return a; } Object snd() { return b; } public String toString() { return "<" + fst().toString() + "," + snd().toString() + ">" ; } } // end Pair /* List of all Delimiters used by the program */ private class Delimiter { private Delimiter neste; private Pair my; public Delimiter(String l, String r) { my= new Pair(new String(l), new String(r)); } public Delimiter() { my= new Pair(null, null); } public void addP(String l, String r) { if (my == null) {my= new Pair(new String(l), new String(r));} else if (neste == null) { neste= new Delimiter(l,r); } else neste.addP(l,r); } public void remSdelim(String s) { if (neste != null) { if (neste.isS(s)) neste = neste.neste(); else neste.remSdelim(s); } } public Delimiter neste() { return neste; } public boolean isS(String s) { if (my != null && (my.fst().toString().equals(s) && my.snd().toString().equals(s))) return true; else return false; } public void remLRdelim(String l, String r) { if (neste != null) { if (neste.isLR(l,r)) neste = neste.neste(); else neste.remLRdelim(l,r); } } public boolean isLR(String l, String r) { if (my != null && (my.fst().toString().equals(l) && my.snd().toString().equals(r))) return true; else return false; } public boolean isInList(String g) { if (my != null && (my.fst().toString().equals(g) || my.snd().toString().equals(g))) return true; else if (neste==null) return false; else return neste.isInList(g); } public boolean isLdelim(String g) { if (my != null && my.fst().toString().equals(g)) return true; else if (neste==null) return false; else return neste.isLdelim(g); } public boolean isRdelim(String g) { if (my != null && my.snd().toString().equals(g)) return true; else if (neste==null) return false; else return neste.isRdelim(g); } public boolean isSingleDelim(String g) { if (my != null && my.fst().toString().equals(g) && my.snd().toString().equals(g)) return true; else if (neste==null) return false; else return neste.isSingleDelim(g); } public boolean match(String l, String r) { if (my != null && my.fst().toString().equals(l) && my.snd().toString().equals(r)) return true; else if (neste==null) return false; else return neste.match(l,r); } } // end Delimiter /* the list of actual Delimiters with the default " " */ private Delimiter delims= new Delimiter(" "," "); /** Delimiters: add a new pair */ public void addDelim(String l, String r) { delims.addP(l,r); } /** Delimiters: add a new delimiter = addDelim(d,d) */ public void addSDelim(String d) { delims.addP(d,d); } /** Delimiters: remove a single delimiter */ public void removeSdelim(String s) { delims.remSdelim(s); } /** Delimiters: remove an L-R delimiter (pair) */ public void removeLRdelim(String l, String r) { delims.remLRdelim(l,r); } /** Delimiters: is g a delimiter string? SPACE (' ') and EOF are delimiters by default.*/ public boolean isDelim(String g) { if (g.length()==1 && (g.charAt(0)==' ' || g.charAt(0)==EOF)) return true; else return delims.isInList(g); } /** Delimiters: is c a delimiter character? */ public boolean isDelim(char c) { if (c==' ' || c==EOF ) return true; return delims.isInList(new String("")+c); } /** Delimiters: is g a left delimiter string? */ public boolean isLdelim(String g) { return delims.isLdelim(g); } /** Delimiters: is g a right delimiter string? */ public boolean isRdelim(String g) { return delims.isRdelim(g); } /** Delimiters: is g a single delimiter string? */ public boolean isSingleDelim(String g) { if (g.length()==1 && g.charAt(0)==' ') return true; else return delims.isSingleDelim(g); } /** Delimiters: is (l,r) a matching pair of delimiters? */ public boolean match(String l, String r) { return delims.match(l,r); } /** Delimiters: skip initial SPACEs and return next token, i.e., either delimiter or a string from the current position to the next delimiter; EOF/isWhitespace terminates any string */ public String NextToken() { char c; c= tegnNB(); String cs= new String("")+c; if (isDelim(cs)) {return cs;} else { String k= new String(""); while (c != EOF && !isDelim(c) && !Character.isWhitespace(c)) { k= k+c; c= tegn(); } unread(); return(k); } } }