All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modelcc.io.file.ReaderCharSequence Maven / Gradle / Ivy

Go to download

ModelCC is a model-based parser generator (a.k.a. compiler compiler) that decouples language specification from language processing, avoiding some of the problems caused by grammar-driven parser generators. ModelCC receives a conceptual model as input, along with constraints that annotate it. It is then able to create a parser for the desired textual language and the generated parser fully automates the instantiation of the language conceptual model. ModelCC also includes a built-in reference resolution mechanism that results in abstract syntax graphs, rather than mere abstract syntax trees.

The newest version!
/*
 * ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
 */

package org.modelcc.io.file;
// package org.openide.compiler;

import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.stream.IntStream;

/**
 * A fake CharSequence based on a Reader. The only way to parse multiline regular expressions
 * from a Reader without loading its entire contents into a memory buffer up front.
 * 
 * Initially its length is optimistically large. Previously read contents are cached.
 * When a char is needed, it is retrieved if necessary from the stream.
 * The currently reported length is also adjusted to be the currently read size
 * plus some horizon value (Integer.MAX_VALUE may be used to set the horizon at
 * infinity for highest accuracy but poor performance for negative searches).
 * When EOF is hit, the length is corrected, and then any attempts to read
 * "past" the end of the file result in U+FFFF (no character).
 * You may prune prefixes of the buffer that you no longer need, to limit memory
 * consumption; in this case attempts to read from the pruned prefix also result
 * in U+FFFF.
 * 
 * @author Jesse Glick
 * @see http://developer.java.sun.com/developer/bugParade/bugs/4607121.html
 * 
 * 
 * Adapted from the org.openide.compiler implementation, 
 * distributed under Sun Public License Version 1.0.
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
 
public final class ReaderCharSequence implements CharSequence 
{    
    /** associated stream */
    private final Reader r;
    /** buffer of characters that have been read */
    private char[] buf;
    /** current length (max index + 1) */
    private int size = 0;
    /** min index, if pruned */
    private int origin = 0;
    /** origin line number */
    private int originLine = 1;
    /** if not eof, reported length (size + some amount) */
    private int horizon;
    /** if true, have hit eof */
    private boolean eof = false;
    /** load factor as for collections */
    private final float loadFactor;
    
    private void invariants() 
    {
        assert buf.length > 0;
        assert size >= 0;
        assert origin >= 0;
        assert origin <= size;
        assert horizon >= size;
        /*
        System.err.println("size=" + size + " origin=" + origin + " horizon=" + horizon + " buf.length=" + buf.length);
        char[] x = new char[buf.length];
        for (int i = 0; i < x.length; i++) {
            char c = buf[i];
            x[i] = (c == '\u0000') ? '#' : c;
        }
        System.err.println(x);
        */
    }
    
    /**
     * Create a sequence from a reader.
     * You probably want this wrapped in a BufferedReader if you haven't already.
     * The initial buffer size is 4Kb, the horizon is set to infinity, and the load factor to 4/3.
     */
    public ReaderCharSequence(Reader r) 
    {
        this(r, 4096, Integer.MAX_VALUE, 4.0f / 3.0f);
    }
    
    /**
     * Create a sequence from a reader with finer control over performance.
     */
    public ReaderCharSequence(Reader r, int bufsize, int horizon, float loadFactor) 
    {
        this.r = r;
        buf = new char[bufsize];
        this.horizon = horizon;
        this.loadFactor = loadFactor;
    }
    
    /**
     * Additional method permitting you to prune an old section of the buffer
     * that will no longer be needed. After this is called, any attempts to
     * read from the interval [0,pos) will yield U+FFFF. Buffer reallocation will
     * only be needed if the current size minus the last prune position is greater
     * than the current buffer size. If the attempted prune position is greater than
     * the actual number of read characters (but less than the reported length), it
     * is quietly limited to the actual size. If the attempted prune position is
     * less than the last set prune position (initially zero, i.e. only for repeated
     * calls) then this method is a no-op (the interval is already pruned).
     * 
     * Typical usage:
     * 
     * ReaderCharSequence s = new ReaderCharSequence(reader);
     * Matcher m = pattern.matcher(s);
     * while (m.find()) {
     *     // as usual
     *     // save memory:
     *     s.prune(m.end());
     * }
     * 
     * @param pos an index to prune before
     * @throws IndexOutOfBoundsException unless 0 <= pos <= length()
     */
    public void prune(int pos) throws IndexOutOfBoundsException 
    {
        if (pos < 0) throw new IndexOutOfBoundsException();
        if (pos > length()) throw new IndexOutOfBoundsException();
        if (pos > origin && pos <= size) {
        	
        	for (int index=origin; index= horizon) {
            throw new IndexOutOfBoundsException();
        }
        while (true) {
            if (index < origin) {
                return '\uFFFF';
            } else if (index < size) {
                return buf[index % buf.length];
            } else if (eof) {
                return '\uFFFF';
            } else {
                readOneChar();
            }
        }
    }

    public int lineAt (int index) 
    {
        if (index < 0 || index >= horizon) {
            throw new IndexOutOfBoundsException();
        } 
        
        while (true) {
            if (index < origin) {
                return 0;
            } else if (index < size) {
            	
            	int line = originLine;
            	for (int i=origin; i nbuf[[origin,size) % l2].
        // XXX faster to use System.arraycopy... figure out the cases (4?)
        for (int i = origin; i < size; i++) {
            nbuf[i % l2] = buf[i % l1];
        }
        buf = nbuf;
        invariants();
    }
    
    public int length() 
    {
    	if (!eof)
    		readOneChar(); // EOF look-ahead
    	
        if (eof) {
            return size;
        } else {
            return horizon;
        }
    }
    
    public CharSequence subSequence(int start, int end) 
    {
        return new SubCharSequence(start, end);
    }
    
    private String substring(int start, int end) 
    {
        assert start >= 0;
        assert start <= end;
        assert end <= size;
        int l = buf.length;
        if (start >= origin && start % l <= end % l) {
            return new String(buf, start % l, end - start);
        } else {
            char[] nbuf = new char[end - start];
            int start2;
            if (start < origin) {
                Arrays.fill(nbuf, 0, origin - start, '\uFFFF');
                start2 = origin;
            } else {
                start2 = start;
            }
            // XXX faster to use System.arraycopy... figure out the cases (2)
            for (int i = start2; i < end; i++) {
                nbuf[i - start] = buf[i % buf.length];
            }
            return new String(nbuf);
        }
    }
    
    public String toString() 
    {
        while (!eof) {
            readOneChar();
        }
        return substring(0, size);
    }

    // JDK8
    
	@Override
	public IntStream chars() 
	{
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public IntStream codePoints() 
	{
		// TODO Auto-generated method stub
		return null;
	}

	
	// SubCharSequence
	
    private final class SubCharSequence implements CharSequence 
    {    
        private final int start;
        private final int end;
        
        public SubCharSequence(int start, int end) 
        {
            this.start = start;
            this.end = end;
        }
        
        public char charAt(int index) 
        {
            if (index < 0 || index >= length()) {
                throw new IndexOutOfBoundsException();
            }
            return ReaderCharSequence.this.charAt(start + index);
        }
        
        public int length() 
        {
            if (eof && start > size) {
                return 0;
            } else if (eof && end > size) {
                return size - start;
            } else {
                return end - start;
            }
        }
        
        public CharSequence subSequence(int start, int end) 
        {
            return new SubCharSequence(this.start + start, this.start + end);
        }
        
        public String toString() 
        {
            while (!eof && end > size) {
                readOneChar();
            }
            if (start > size) {
                return new String();
            } else if (end > size) {
                return substring(start, size);
            } else {
                return substring(start, end);
            }
        }

        // JDK 8
        
		@Override
		public IntStream chars() 
		{
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public IntStream codePoints() 
		{
			// TODO Auto-generated method stub
			return null;
		}
        
    }    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy