blob: fd670016af1973df9512c82a042c12e4f78ec13a [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.royale.compiler.internal.parsing;
import java.io.IOException;
import java.io.Reader;
import org.apache.royale.utils.NonLockingStringReader;
/**
* Reader that spoofs adding several characters to the end of the existing Reader. Reading from the
* FakingReader returns characters from the original Reader until they run out, at which point it returns
* characters from its buffer of fake characters
*/
public class FakingReader extends Reader
{
/**
* Constructor
* @param reader the original reader
* @param fakeCharacters the fake characters to "append" to the end
*/
public FakingReader(Reader reader, String fakeCharacters)
{
super();
this.reader = reader;
fakeReader = new NonLockingStringReader(fakeCharacters);
readingFakeCharacters = false;
// See the comments on mungeDifficultCharacters(), below
// fMungeDifficultCharacters = mungeDifficultCharacters;
// fOffset = 0;
// fDifficultCharacters = new ArrayList();
// fDifficultCharacterOffsets = new ArrayList();
}
/**
* The original Reader that contains the real characters
*/
protected Reader reader;
/**
* The StringReader that contains the fake characters
*/
protected NonLockingStringReader fakeReader;
/**
* Flag indicating which reader is currently in use
*/
protected boolean readingFakeCharacters;
/**
* @see java.io.Reader#close()
*/
@Override
public void close() throws IOException
{
reader.close();
}
// /**
// * Flag indicating that we should munge difficult characters to prepare for JLex
// */
// protected boolean fMungeDifficultCharacters;
// /**
// * Current offset into the stream
// */
// protected int fOffset;
// /**
// * List of difficult characters that we've had to munge before sending to JLex
// */
// protected ArrayList fDifficultCharacters;
// /**
// * List of offsets at which we've had to munge characters before sending to JLex
// */
// protected ArrayList fDifficultCharacterOffsets;
// /**
// * Locate any identifier-legal characters that we know we'll have trouble
// * identifying in the tokenizer, and replace them with simpler characters.
// * This is designed to be called after reading characters (from the real
// * stream) and read()
// *
// * @param cbuf buffer of characters just filled in read()
// * @param off the offset at which read() just put the characters
// * @param len the number of character successfully read
// */
// protected void mungeDifficultCharacters(char[] cbuf, int off, int len)
// {
// // The following are all legal identifier characters in ECMAScript
// // Uppercase letter (Lu)
// // Lowercase letter (Ll)
// // Titlecase letter (Lt)
// // Modifier letter (Lm)
// // Other letter (Lo)
// // Letter number (Nl) *
// // $ and _
// // Unicode escape sequence (\uFFFF)
// // Non-spacing mark (Mn) *
// // Combining spacing mark (Mc) *
// // Decimal number (Nd)
// // Connector punctuation (Pc) *
// //
// // In JLex, we can use the builtin character classes
// // [:letter:] = Character.isLetter() = Lu + Ll + Lt + Lm + Lo
// // [:digit:] = Character.isDigit() = Nd
// // and we can use simple regular expressions to handle $ and _
// // and the Unicode escape sequence (\uFFFF). The other classes
// // (Nl, Mn, Mc, Nd, Pc) are not easy to identify in JLex, since there's
// // no generic character class support. We'll identify the characters
// // here and replace them with something more easily managed, then we'll
// // unmunge the tokens in ASTokenizer before we do anything else with them.
//
// for (int i = off; i < off + len; i++)
// {
// if (Character.getType(cbuf[i]) == Character.LETTER_NUMBER)
// {
// // This is a valid starting character for an identifier, so
// // "a" is a suitable equivalent
// fDifficultCharacterOffsets.add(new Integer(fOffset + i - off));
// fDifficultCharacters.add(new Character(cbuf[i]));
// cbuf[i] = 'a';
// }
// else if (cbuf[i] != '_' &&
// (Character.getType(cbuf[i]) == Character.NON_SPACING_MARK ||
// Character.getType(cbuf[i]) == Character.COMBINING_SPACING_MARK ||
// Character.getType(cbuf[i]) == Character.CONNECTOR_PUNCTUATION))
// {
// // This is not a valid starting character for an identifier, but
// // is a valid following character for an identifier, so "0" is a
// // suitable equivalent
// fDifficultCharacterOffsets.add(new Integer(fOffset + i - off));
// fDifficultCharacters.add(new Character(cbuf[i]));
// cbuf[i] = '0';
// }
// }
// }
// /**
// * Undo any character transformation that we accomplished in mungeDifficultCharacters
// * @param tokenString the token string that came back from the tokenizer
// * (possibly containing transformed characters)
// * @param startOffset the start offset of that string
// * @return the same string, with the original characters put back
// */
// public String unmungeDifficultCharacters(String tokenString, int startOffset)
// {
// int endOffset = startOffset + tokenString.length();
// char [] tokenChars = null;
// for (int i = 0; i < fDifficultCharacterOffsets.size(); i++)
// {
// int difficultCharacterOffset = ((Integer)fDifficultCharacterOffsets.get(i)).intValue();
// if (difficultCharacterOffset >= startOffset &&
// difficultCharacterOffset <= endOffset)
// {
// if (tokenChars == null)
// tokenChars = tokenString.toCharArray();
// tokenChars[difficultCharacterOffset - startOffset] =
// ((Character)fDifficultCharacters.get(i)).charValue();
// }
// else if (difficultCharacterOffset > endOffset)
// {
// break;
// }
// }
// if (tokenChars != null)
// tokenString = new String(tokenChars);
// return tokenString;
// }
/**
* @see java.io.Reader#read(char[], int, int)
*/
@Override
public int read(char[] cbuf, int off, int len) throws IOException
{
if (readingFakeCharacters)
{
// We're already past the end of the real stream and in the fake characters
return fakeReader.read(cbuf, off, len);
}
int charactersRead = reader.read(cbuf, off, len);
if (charactersRead == -1)
{
// We're past the end of the real stream and in the fake characters
readingFakeCharacters = true;
return fakeReader.read(cbuf, off, len);
}
// See the comments on mungeDifficultCharacters(), above
// if (fMungeDifficultCharacters)
// {
// mungeDifficultCharacters(cbuf, off, charactersRead);
// fOffset += charactersRead;
// }
// We're still reading characters from the real stream.
return charactersRead;
}
}