From: Dale A. <dal...@us...> - 2006-05-23 22:20:33
|
Update of /cvsroot/jedit/plugins/PropertySideKick/src/sidekick/property/parser/property In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv26005/src/sidekick/property/parser/property Added Files: JavaCharStream.java Location.java ParseException.java Property.java PropertyParser.java PropertyParser.jj PropertyParserConstants.java PropertyParserTokenManager.java Token.java TokenMgrError.java Log Message: Adding a sidekick for property files. --- NEW FILE: TokenMgrError.java --- /* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ package sidekick.property.parser.property; public class TokenMgrError extends Error { /* * Ordinals for various reasons why an Error of this type can be thrown. */ /** * Lexical error occured. */ static final int LEXICAL_ERROR = 0; /** * An attempt wass made to create a second instance of a static token manager. */ static final int STATIC_LEXER_ERROR = 1; /** * Tried to change to an invalid lexical state. */ static final int INVALID_LEXICAL_STATE = 2; /** * Detected (and bailed out of) an infinite loop in the token manager. */ static final int LOOP_DETECTED = 3; /** * Indicates the reason why the exception is thrown. It will have * one of the above 4 values. */ int errorCode; /** * Replaces unprintable characters by their espaced (or unicode escaped) * equivalents in the given string */ protected static final String addEscapes(String str) { StringBuffer retval = new StringBuffer(); char ch; for (int i = 0; i < str.length(); i++) { switch (str.charAt(i)) { case 0 : continue; case '\b': retval.append("\\b"); continue; case '\t': retval.append("\\t"); continue; case '\n': retval.append("\\n"); continue; case '\f': retval.append("\\f"); continue; case '\r': retval.append("\\r"); continue; case '\"': retval.append("\\\""); continue; case '\'': retval.append("\\\'"); continue; case '\\': retval.append("\\\\"); continue; default: if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { String s = "0000" + Integer.toString(ch, 16); retval.append("\\u" + s.substring(s.length() - 4, s.length())); } else { retval.append(ch); } continue; } } return retval.toString(); } /** * Returns a detailed message for the Error when it is thrown by the * token manager to indicate a lexical error. * Parameters : * EOFSeen : indicates if EOF caused the lexicl error * curLexState : lexical state in which this error occured * errorLine : line number when the error occured * errorColumn : column number when the error occured * errorAfter : prefix that was seen before this error occured * curchar : the offending character * Note: You can customize the lexical error message by modifying this method. */ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { return("Lexical error at line " + errorLine + ", column " + errorColumn + ". Encountered: " + (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + "after : \"" + addEscapes(errorAfter) + "\""); } /** * You can also modify the body of this method to customize your error messages. * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not * of end-users concern, so you can return something like : * * "Internal Error : Please file a bug report .... " * * from this method for such cases in the release version of your parser. */ public String getMessage() { return super.getMessage(); } /* * Constructors of various flavors follow. */ public TokenMgrError() { } public TokenMgrError(String message, int reason) { super(message); errorCode = reason; } public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); } } --- NEW FILE: Token.java --- /* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ package sidekick.property.parser.property; /** * Describes the input token stream. */ public class Token { /** * An integer that describes the kind of this token. This numbering * system is determined by JavaCCParser, and a table of these numbers is * stored in the file ...Constants.java. */ public int kind; /** * beginLine and beginColumn describe the position of the first character * of this token; endLine and endColumn describe the position of the * last character of this token. */ public int beginLine, beginColumn, endLine, endColumn; /** * The string image of the token. */ public String image; /** * A reference to the next regular (non-special) token from the input * stream. If this is the last token from the input stream, or if the * token manager has not read tokens beyond this one, this field is * set to null. This is true only if this token is also a regular * token. Otherwise, see below for a description of the contents of * this field. */ public Token next; /** * This field is used to access special tokens that occur prior to this * token, but after the immediately preceding regular (non-special) token. * If there are no such special tokens, this field is set to null. * When there are more than one such special token, this field refers * to the last of these special tokens, which in turn refers to the next * previous special token through its specialToken field, and so on * until the first special token (whose specialToken field is null). * The next fields of special tokens refer to other special tokens that * immediately follow it (without an intervening regular token). If there * is no such token, this field is null. */ public Token specialToken; /** * Returns the image. */ public String toString() { return image; } /** * Returns a new Token object, by default. However, if you want, you * can create and return subclass objects based on the value of ofKind. * Simply add the cases to the switch for all those special cases. * For example, if you have a subclass of Token called IDToken that * you want to create if ofKind is ID, simlpy add something like : * * case MyParserConstants.ID : return new IDToken(); * * to the following switch statement. Then you can cast matchedToken * variable to the appropriate type and use it in your lexical actions. */ public static final Token newToken(int ofKind) { switch(ofKind) { default : return new Token(); } } } --- NEW FILE: PropertyParser.java --- /* Generated By:JavaCC: Do not edit this line. PropertyParser.java */ package sidekick.property.parser.property; import java.util.*; public class PropertyParser implements PropertyParserConstants { // accumulates parse exceptions private List<ParseException> exceptions = new ArrayList(); // for testing... public static void main(String args[]) throws ParseException { PropertyParser parser = new PropertyParser(System.in); parser.Properties(); } // utility to trim horizontal whitespace from the front of a string public String trimFront(String s) { if (s == null || s.length() == 0) { return s; } int index = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == ' ' || s.charAt(i) == '\t') ++index; else break; } return s.substring(index); } // setting the tab size makes the token locations more accurate public void setTabSize(int size) { jj_input_stream.setTabSize(size); } public int getTabSize() { return jj_input_stream.getTabSize(0); } // creates a start location from the given token public Location createStartLocation(Token t) { if (t == null) return new Location(0, 0); return new Location(t.beginLine, t.beginColumn); } // creates an end location from the given token public Location createEndLocation(Token t) { if (t == null) return new Location(0, 0); return new Location(t.endLine, t.endColumn); } // add an exception to the list of exceptions public void addException(ParseException pe) { if (pe != null) exceptions.add(pe); } // return the list of ParseExceptions public List<ParseException> getExceptions() { return exceptions; } final public List<Property> Properties() throws ParseException { List list = new ArrayList(); Property p = null; label_1: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case COMMENT: case BARE_KEY: case KEY: ; break; default: jj_la1[0] = jj_gen; break label_1; } if (jj_2_1(2)) { Comment(); } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case BARE_KEY: case KEY: p = Property(); if (p != null) list.add(p); break; default: jj_la1[1] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } jj_consume_token(0); Collections.sort(list); {if (true) return list;} throw new Error("Missing return statement in function"); } final public Property Property() throws ParseException { Token key = null; Token value = null; try { if (jj_2_2(2)) { key = jj_consume_token(KEY); token_source.SwitchTo(ParseEquals); jj_consume_token(EQUALS); token_source.SwitchTo(ParseValue); value = jj_consume_token(VALUE); } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case BARE_KEY: key = jj_consume_token(BARE_KEY); token_source.SwitchTo(DEFAULT); break; default: jj_la1[2] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } Property prop = new Property(); prop.setStartLocation(createStartLocation(key)); prop.setEndLocation(createEndLocation(value == null ? key : value)); /* key -- need to trim as the regex production can capture whitespace, and by definition, the key cannot contain any whitespace characters */ String out = key.image.trim(); // key can have escaped 'equals' characters, unescape them out = out.replaceAll("\\\\=", "="); out = out.replaceAll("\\\\:", ":"); out = out.replaceAll("\\\\ ", " "); out = out.replaceAll("\\\\\\t", "\t"); prop.setKey(out); /* value -- need to combine multi-line values into a single line. Leading whitespace on continuation lines is discarded, as is leading whitespace at the start of the value. */ out = value == null ? "" : value.image.replaceAll("\\\\(\\s)+", ""); out = trimFront(out); prop.setValue(out); {if (true) return prop;} } catch (ParseException e) { addException(generateParseException()); } throw new Error("Missing return statement in function"); } final public void Comment() throws ParseException { jj_consume_token(COMMENT); } final private boolean jj_2_1(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_1(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(0, xla); } } final private boolean jj_2_2(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_2(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(1, xla); } } final private boolean jj_3_2() { if (jj_scan_token(KEY)) return true; if (jj_scan_token(EQUALS)) return true; return false; } final private boolean jj_3_1() { if (jj_scan_token(4)) return true; return false; } public PropertyParserTokenManager token_source; JavaCharStream jj_input_stream; public Token token, jj_nt; private int jj_ntk; private Token jj_scanpos, jj_lastpos; private int jj_la; public boolean lookingAhead = false; private boolean jj_semLA; private int jj_gen; final private int[] jj_la1 = new int[3]; static private int[] jj_la1_0; static { jj_la1_0(); } private static void jj_la1_0() { jj_la1_0 = new int[] {0x70,0x60,0x20,}; } final private JJCalls[] jj_2_rtns = new JJCalls[2]; private boolean jj_rescan = false; private int jj_gc = 0; public PropertyParser(java.io.InputStream stream) { this(stream, null); } public PropertyParser(java.io.InputStream stream, String encoding) { try { jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } token_source = new PropertyParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 3; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public void ReInit(java.io.InputStream stream) { ReInit(stream, null); } public void ReInit(java.io.InputStream stream, String encoding) { try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 3; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public PropertyParser(java.io.Reader stream) { jj_input_stream = new JavaCharStream(stream, 1, 1); token_source = new PropertyParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 3; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public void ReInit(java.io.Reader stream) { jj_input_stream.ReInit(stream, 1, 1); token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 3; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public PropertyParser(PropertyParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 3; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public void ReInit(PropertyParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 3; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } final private Token jj_consume_token(int kind) throws ParseException { Token oldToken; if ((oldToken = token).next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; if (token.kind == kind) { jj_gen++; if (++jj_gc > 100) { jj_gc = 0; for (int i = 0; i < jj_2_rtns.length; i++) { JJCalls c = jj_2_rtns[i]; while (c != null) { if (c.gen < jj_gen) c.first = null; c = c.next; } } } return token; } token = oldToken; jj_kind = kind; throw generateParseException(); } static private final class LookaheadSuccess extends java.lang.Error { } final private LookaheadSuccess jj_ls = new LookaheadSuccess(); final private boolean jj_scan_token(int kind) { if (jj_scanpos == jj_lastpos) { jj_la--; if (jj_scanpos.next == null) { jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); } else { jj_lastpos = jj_scanpos = jj_scanpos.next; } } else { jj_scanpos = jj_scanpos.next; } if (jj_rescan) { int i = 0; Token tok = token; while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } if (tok != null) jj_add_error_token(kind, i); } if (jj_scanpos.kind != kind) return true; if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; return false; } final public Token getNextToken() { if (token.next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; jj_gen++; return token; } final public Token getToken(int index) { Token t = lookingAhead ? jj_scanpos : token; for (int i = 0; i < index; i++) { if (t.next != null) t = t.next; else t = t.next = token_source.getNextToken(); } return t; } final private int jj_ntk() { if ((jj_nt=token.next) == null) return (jj_ntk = (token.next=token_source.getNextToken()).kind); else return (jj_ntk = jj_nt.kind); } private java.util.Vector jj_expentries = new java.util.Vector(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; private int jj_endpos; private void jj_add_error_token(int kind, int pos) { if (pos >= 100) return; if (pos == jj_endpos + 1) { jj_lasttokens[jj_endpos++] = kind; } else if (jj_endpos != 0) { jj_expentry = new int[jj_endpos]; for (int i = 0; i < jj_endpos; i++) { jj_expentry[i] = jj_lasttokens[i]; } boolean exists = false; for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) { int[] oldentry = (int[])(e.nextElement()); if (oldentry.length == jj_expentry.length) { exists = true; for (int i = 0; i < jj_expentry.length; i++) { if (oldentry[i] != jj_expentry[i]) { exists = false; break; } } if (exists) break; } } if (!exists) jj_expentries.addElement(jj_expentry); if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; } } public ParseException generateParseException() { jj_expentries.removeAllElements(); boolean[] la1tokens = new boolean[10]; for (int i = 0; i < 10; i++) { la1tokens[i] = false; } if (jj_kind >= 0) { la1tokens[jj_kind] = true; jj_kind = -1; } for (int i = 0; i < 3; i++) { if (jj_la1[i] == jj_gen) { for (int j = 0; j < 32; j++) { if ((jj_la1_0[i] & (1<<j)) != 0) { la1tokens[j] = true; } } } } for (int i = 0; i < 10; i++) { if (la1tokens[i]) { jj_expentry = new int[1]; jj_expentry[0] = i; jj_expentries.addElement(jj_expentry); } } jj_endpos = 0; jj_rescan_token(); jj_add_error_token(0, 0); int[][] exptokseq = new int[jj_expentries.size()][]; for (int i = 0; i < jj_expentries.size(); i++) { exptokseq[i] = (int[])jj_expentries.elementAt(i); } return new ParseException(token, exptokseq, tokenImage); } final public void enable_tracing() { } final public void disable_tracing() { } final private void jj_rescan_token() { jj_rescan = true; for (int i = 0; i < 2; i++) { try { JJCalls p = jj_2_rtns[i]; do { if (p.gen > jj_gen) { jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; switch (i) { case 0: jj_3_1(); break; case 1: jj_3_2(); break; } } p = p.next; } while (p != null); } catch(LookaheadSuccess ls) { } } jj_rescan = false; } final private void jj_save(int index, int xla) { JJCalls p = jj_2_rtns[index]; while (p.gen > jj_gen) { if (p.next == null) { p = p.next = new JJCalls(); break; } p = p.next; } p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; } static final class JJCalls { int gen; Token first; int arg; JJCalls next; } } --- NEW FILE: PropertyParser.jj --- /* Copyright (c) 2006, Dale Anson All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Simple parser to read Java property files. See Sun's javadoc for java.util.Properties.load() for the specification of a property file, that's what I used as the rules for this parser. */ options { JAVA_UNICODE_ESCAPE = true; STATIC = false; } PARSER_BEGIN(PropertyParser) package sidekick.property.parser.property; import java.util.*; public class PropertyParser { // accumulates parse exceptions private List<ParseException> exceptions = new ArrayList(); // for testing... public static void main(String args[]) throws ParseException { PropertyParser parser = new PropertyParser(System.in); parser.Properties(); } /** * Utility to trim horizontal whitespace from the front of a string. * @param the string to trim * @return the trimmed string */ public String trimFront(String s) { if (s == null || s.length() == 0) { return s; } int index = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == ' ' || s.charAt(i) == '\t') ++index; else break; } return s.substring(index); } /** * Setting the tab size makes the token locations more accurate. * @param size the size of the tabs in the current jEdit buffer */ public void setTabSize(int size) { jj_input_stream.setTabSize(size); } /** * @return the current tab size that the parser is using */ public int getTabSize() { return jj_input_stream.getTabSize(0); } /** * Creates a start location from the given token. * @param t a token * @return the start location of the token. */ public Location createStartLocation(Token t) { if (t == null) return new Location(0, 0); return new Location(t.beginLine, t.beginColumn); } /** * Creates an end location from the given token. * @param t a token * @return the end location of the token. */ public Location createEndLocation(Token t) { if (t == null) return new Location(0, 0); return new Location(t.endLine, t.endColumn); } /** * Add an exception to the list of exceptions. Rather than failing on * any exception, this parser will continue parsing and will accumulate * any/all exceptions. * @param pe a ParseException to accumulate */ public void addException(ParseException pe) { if (pe != null) exceptions.add(pe); } /** * @return the list of accumulated ParseExceptions */ public List<ParseException> getExceptions() { return exceptions; } } PARSER_END(PropertyParser) /* skip blank lines and continuation characters */ SKIP: { <NEWLINE: (["\r", "\n"])+ > | <BLANK_LINE: ([" ", "\t"])+(<NEWLINE>) > | <CONTINUATION: ("\\")(<NEWLINE>) > } <DEFAULT> TOKEN : { /* comments are single line only. They start with # or ! as the first non- whitespace character and extend to the end of the line. Comments cannot go at the end of a key/value line -- they will be treated as part of the value, NOT as a comment! */ <COMMENT: ([" ", "\t"])*("#" | "!")(~["\r", "\n"])*(<NEWLINE>) > : DEFAULT | /* a key with no value is assumed to have an empty value */ <BARE_KEY: (([" ", "\t"])*((("\\") ( ":" | "=" | " " | "\t" )) | (~[" ", "\t", "=", ":", "#"]))+ (<NEWLINE>)) > : DEFAULT | /* a key actually starts with the first non-whitespace character on a line and extends through the last character before the first horizontal whitespace character or : or =. This means that a key cannot contain any whitespace characters. Note that a key can have escaped space and tab and : and = as part of the key name. */ <KEY: ([" ", "\t"])*((("\\") ( ":" | "=" | " " | "\t" )) | (~[" ", "\t", "=", ":", "#"]))+ > : ParseEquals | <OTHER: ~[] > } <ParseEquals> TOKEN : { /* the equals may be horizontal whitespace or = or :. There can be horizontal whitespace before and after the = and :. I'm not worrying about the trailing whitespace here, that gets captured by the VALUE regex and is trimmed in the bnf production below. */ <EQUALS: ([" ", "\t"])*("=") | ([" ", "\t"])*(":") | ([" ", "\t"])+ > : ParseValue } <ParseValue> TOKEN: { /* the value actually starts with the first non-horizontal whitespace character following the EQUALS, but this regex will also capture the horizontal whitespace following the EQUALS. This whitespace is trimmed in the bnf production below. The value can span several lines if the continuation character is the last character on the line. This needs work -- the value can have escaped \ characters, and I'm not checking if that's the case. For example, if a line ends in \\, then it's an escaped \, not a continuation character, and should be part of the value. I think this is a rare use case, so I'm not going to worry about it until someone complains. */ <VALUE: ((~["\r", "\n"])*(<CONTINUATION>)*)+(<NEWLINE>)? > : DEFAULT } List<Property> Properties() : { List list = new ArrayList(); Property p = null; } { /* Property files are simple, there are either comments or properties, there is nothing else. */ ( LOOKAHEAD(2) ( Comment() ) | ( p = Property() { if (p != null) list.add(p); } ) )* <EOF> { /* always sort the list by property name -- could make the caller do this and just return the properties in the original order */ Collections.sort(list); return list; } } /** * @return a single property from the property file. */ Property Property() : { Token key = null; Token value = null; } { try { ( LOOKAHEAD(2) ( key=<KEY> { token_source.SwitchTo(ParseEquals); } <EQUALS> { token_source.SwitchTo(ParseValue); } value=<VALUE> ) | ( key=<BARE_KEY> { token_source.SwitchTo(DEFAULT); } ) ) { Property prop = new Property(); prop.setStartLocation(createStartLocation(key)); prop.setEndLocation(createEndLocation(value == null ? key : value)); /* key -- need to trim as the regex production can capture whitespace, and by definition, the key cannot contain any whitespace characters */ String out = key.image.trim(); /* key can have escaped 'equals' characters, unescape them */ out = out.replaceAll("\\\\=", "="); out = out.replaceAll("\\\\:", ":"); out = out.replaceAll("\\\\ ", " "); out = out.replaceAll("\\\\\\t", "\t"); prop.setKey(out); /* value -- need to combine multi-line values into a single line. Leading whitespace on continuation lines is discarded, as is leading whitespace at the start of the value. */ out = value == null ? "" : value.image.replaceAll("\\\\(\\s)+", ""); out = trimFront(out); prop.setValue(out); return prop; } } catch (ParseException e) { addException(generateParseException()); } } /* For completeness only. This parser does nothing special with comments. */ void Comment() : {} { <COMMENT> } --- NEW FILE: PropertyParserConstants.java --- /* Generated By:JavaCC: Do not edit this line. PropertyParserConstants.java */ package sidekick.property.parser.property; public interface PropertyParserConstants { int EOF = 0; int NEWLINE = 1; int BLANK_LINE = 2; int CONTINUATION = 3; int COMMENT = 4; int BARE_KEY = 5; int KEY = 6; int OTHER = 7; int EQUALS = 8; int VALUE = 9; int DEFAULT = 0; int ParseEquals = 1; int ParseValue = 2; String[] tokenImage = { "<EOF>", "<NEWLINE>", "<BLANK_LINE>", "<CONTINUATION>", "<COMMENT>", "<BARE_KEY>", "<KEY>", "<OTHER>", "<EQUALS>", "<VALUE>", }; } --- NEW FILE: JavaCharStream.java --- /* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 4.0 */ package sidekick.property.parser.property; /** * An implementation of interface CharStream, where the stream is assumed to * contain only ASCII characters (with java-like unicode escape processing). */ public class JavaCharStream { public static final boolean staticFlag = false; static final int hexval(char c) throws java.io.IOException { switch(c) { case '0' : return 0; case '1' : return 1; case '2' : return 2; case '3' : return 3; case '4' : return 4; case '5' : return 5; case '6' : return 6; case '7' : return 7; case '8' : return 8; case '9' : return 9; case 'a' : case 'A' : return 10; case 'b' : case 'B' : return 11; case 'c' : case 'C' : return 12; case 'd' : case 'D' : return 13; case 'e' : case 'E' : return 14; case 'f' : case 'F' : return 15; } throw new java.io.IOException(); // Should never come here } public int bufpos = -1; int bufsize; int available; int tokenBegin; protected int bufline[]; protected int bufcolumn[]; protected int column = 0; protected int line = 1; protected boolean prevCharIsCR = false; protected boolean prevCharIsLF = false; protected java.io.Reader inputStream; protected char[] nextCharBuf; protected char[] buffer; protected int maxNextCharInd = 0; protected int nextCharInd = -1; protected int inBuf = 0; protected int tabSize = 8; protected void setTabSize(int i) { tabSize = i; } protected int getTabSize(int i) { return tabSize; } protected void ExpandBuff(boolean wrapAround) { char[] newbuffer = new char[bufsize + 2048]; int newbufline[] = new int[bufsize + 2048]; int newbufcolumn[] = new int[bufsize + 2048]; try { if (wrapAround) { System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); buffer = newbuffer; System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); bufline = newbufline; System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); bufcolumn = newbufcolumn; bufpos += (bufsize - tokenBegin); } else { System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); buffer = newbuffer; System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); bufline = newbufline; System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); bufcolumn = newbufcolumn; bufpos -= tokenBegin; } } catch (Throwable t) { throw new Error(t.getMessage()); } available = (bufsize += 2048); tokenBegin = 0; } protected void FillBuff() throws java.io.IOException { int i; if (maxNextCharInd == 4096) maxNextCharInd = nextCharInd = 0; try { if ((i = inputStream.read(nextCharBuf, maxNextCharInd, 4096 - maxNextCharInd)) == -1) { inputStream.close(); throw new java.io.IOException(); } else maxNextCharInd += i; return; } catch(java.io.IOException e) { if (bufpos != 0) { --bufpos; backup(0); } else { bufline[bufpos] = line; bufcolumn[bufpos] = column; } throw e; } } protected char ReadByte() throws java.io.IOException { if (++nextCharInd >= maxNextCharInd) FillBuff(); return nextCharBuf[nextCharInd]; } public char BeginToken() throws java.io.IOException { if (inBuf > 0) { --inBuf; if (++bufpos == bufsize) bufpos = 0; tokenBegin = bufpos; return buffer[bufpos]; } tokenBegin = 0; bufpos = -1; return readChar(); } protected void AdjustBuffSize() { if (available == bufsize) { if (tokenBegin > 2048) { bufpos = 0; available = tokenBegin; } else ExpandBuff(false); } else if (available > tokenBegin) available = bufsize; else if ((tokenBegin - available) < 2048) ExpandBuff(true); else available = tokenBegin; } protected void UpdateLineColumn(char c) { column++; if (prevCharIsLF) { prevCharIsLF = false; line += (column = 1); } else if (prevCharIsCR) { prevCharIsCR = false; if (c == '\n') { prevCharIsLF = true; } else line += (column = 1); } switch (c) { case '\r' : prevCharIsCR = true; break; case '\n' : prevCharIsLF = true; break; case '\t' : column--; column += (tabSize - (column % tabSize)); break; default : break; } bufline[bufpos] = line; bufcolumn[bufpos] = column; } public char readChar() throws java.io.IOException { if (inBuf > 0) { --inBuf; if (++bufpos == bufsize) bufpos = 0; return buffer[bufpos]; } char c; if (++bufpos == available) AdjustBuffSize(); if ((buffer[bufpos] = c = ReadByte()) == '\\') { UpdateLineColumn(c); int backSlashCnt = 1; for (;;) // Read all the backslashes { if (++bufpos == available) AdjustBuffSize(); try { if ((buffer[bufpos] = c = ReadByte()) != '\\') { UpdateLineColumn(c); // found a non-backslash char. if ((c == 'u') && ((backSlashCnt & 1) == 1)) { if (--bufpos < 0) bufpos = bufsize - 1; break; } backup(backSlashCnt); return '\\'; } } catch(java.io.IOException e) { if (backSlashCnt > 1) backup(backSlashCnt); return '\\'; } UpdateLineColumn(c); backSlashCnt++; } // Here, we have seen an odd number of backslash's followed by a 'u' try { while ((c = ReadByte()) == 'u') ++column; buffer[bufpos] = c = (char)(hexval(c) << 12 | hexval(ReadByte()) << 8 | hexval(ReadByte()) << 4 | hexval(ReadByte())); column += 4; } catch(java.io.IOException e) { throw new Error("Invalid escape character at line " + line + " column " + column + "."); } if (backSlashCnt == 1) return c; else { backup(backSlashCnt - 1); return '\\'; } } else { UpdateLineColumn(c); return (c); } } /** * @deprecated * @see #getEndColumn */ public int getColumn() { return bufcolumn[bufpos]; } /** * @deprecated * @see #getEndLine */ public int getLine() { return bufline[bufpos]; } public int getEndColumn() { return bufcolumn[bufpos]; } public int getEndLine() { return bufline[bufpos]; } public int getBeginColumn() { return bufcolumn[tokenBegin]; } public int getBeginLine() { return bufline[tokenBegin]; } public void backup(int amount) { inBuf += amount; if ((bufpos -= amount) < 0) bufpos += bufsize; } public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; available = bufsize = buffersize; buffer = new char[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; nextCharBuf = new char[4096]; } public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn) { this(dstream, startline, startcolumn, 4096); } public JavaCharStream(java.io.Reader dstream) { this(dstream, 1, 1, 4096); } public void ReInit(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; if (buffer == null || buffersize != buffer.length) { available = bufsize = buffersize; buffer = new char[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; nextCharBuf = new char[4096]; } prevCharIsLF = prevCharIsCR = false; tokenBegin = inBuf = maxNextCharInd = 0; nextCharInd = bufpos = -1; } public void ReInit(java.io.Reader dstream, int startline, int startcolumn) { ReInit(dstream, startline, startcolumn, 4096); } public void ReInit(java.io.Reader dstream) { ReInit(dstream, 1, 1, 4096); } public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); } public JavaCharStream(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); } public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn) throws java.io.UnsupportedEncodingException { this(dstream, encoding, startline, startcolumn, 4096); } public JavaCharStream(java.io.InputStream dstream, int startline, int startcolumn) { this(dstream, startline, startcolumn, 4096); } public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { this(dstream, encoding, 1, 1, 4096); } public JavaCharStream(java.io.InputStream dstream) { this(dstream, 1, 1, 4096); } public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); } public void ReInit(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); } public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn) throws java.io.UnsupportedEncodingException { ReInit(dstream, encoding, startline, startcolumn, 4096); } public void ReInit(java.io.InputStream dstream, int startline, int startcolumn) { ReInit(dstream, startline, startcolumn, 4096); } public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { ReInit(dstream, encoding, 1, 1, 4096); } public void ReInit(java.io.InputStream dstream) { ReInit(dstream, 1, 1, 4096); } public String GetImage() { if (bufpos >= tokenBegin) return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); else return new String(buffer, tokenBegin, bufsize - tokenBegin) + new String(buffer, 0, bufpos + 1); } public char[] GetSuffix(int len) { char[] ret = new char[len]; if ((bufpos + 1) >= len) System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); else { System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, len - bufpos - 1); System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); } return ret; } public void Done() { nextCharBuf = null; buffer = null; bufline = null; bufcolumn = null; } /** * Method to adjust line and column numbers for the start of a token. */ public void adjustBeginLineColumn(int newLine, int newCol) { int start = tokenBegin; int len; if (bufpos >= tokenBegin) { len = bufpos - tokenBegin + inBuf + 1; } else { len = bufsize - tokenBegin + bufpos + 1 + inBuf; } int i = 0, j = 0, k = 0; int nextColDiff = 0, columnDiff = 0; while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { bufline[j] = newLine; nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; bufcolumn[j] = newCol + columnDiff; columnDiff = nextColDiff; i++; } if (i < len) { bufline[j] = newLine++; bufcolumn[j] = newCol + columnDiff; while (i++ < len) { if (bufline[j = start % bufsize] != bufline[++start % bufsize]) bufline[j] = newLine++; else bufline[j] = newLine; } } line = bufline[j]; column = bufcolumn[j]; } } --- NEW FILE: ParseException.java --- /* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ package sidekick.property.parser.property; /** * This exception is thrown when parse errors are encountered. * You can explicitly create objects of this exception type by * calling the method generateParseException in the generated * parser. * * You can modify this class to customize your error reporting * mechanisms so long as you retain the public fields. */ public class ParseException extends Exception { /** * This constructor is used by the method "generateParseException" * in the generated parser. Calling this constructor generates * a new object of this type with the fields "currentToken", * "expectedTokenSequences", and "tokenImage" set. The boolean * flag "specialConstructor" is also set to true to indicate that * this constructor was used to create this object. * This constructor calls its super class with the empty string * to force the "toString" method of parent class "Throwable" to * print the error message in the form: * ParseException: <result of getMessage> */ public ParseException(Token currentTokenVal, int[][] expectedTokenSequencesVal, String[] tokenImageVal ) { super(""); specialConstructor = true; currentToken = currentTokenVal; expectedTokenSequences = expectedTokenSequencesVal; tokenImage = tokenImageVal; } /** * The following constructors are for use by you for whatever * purpose you can think of. Constructing the exception in this * manner makes the exception behave in the normal way - i.e., as * documented in the class "Throwable". The fields "errorToken", * "expectedTokenSequences", and "tokenImage" do not contain * relevant information. The JavaCC generated code does not use * these constructors. */ public ParseException() { super(); specialConstructor = false; } public ParseException(String message) { super(message); specialConstructor = false; } /** * This variable determines which constructor was used to create * this object and thereby affects the semantics of the * "getMessage" method (see below). */ protected boolean specialConstructor; /** * This is the last token that has been consumed successfully. If * this object has been created due to a parse error, the token * followng this token will (therefore) be the first error token. */ public Token currentToken; /** * Each entry in this array is an array of integers. Each array * of integers represents a sequence of tokens (by their ordinal * values) that is expected at this point of the parse. */ public int[][] expectedTokenSequences; /** * This is a reference to the "tokenImage" array of the generated * parser within which the parse error occurred. This array is * defined in the generated ...Constants interface. */ public String[] tokenImage; /** * This method has the standard behavior when this object has been * created using the standard constructors. Otherwise, it uses * "currentToken" and "expectedTokenSequences" to generate a parse * error message and returns it. If this object has been created * due to a parse error, and you do not catch it (it gets thrown * from the parser), then this method is called during the printing * of the final stack trace, and hence the correct error message * gets displayed. */ public String getMessage() { if (!specialConstructor) { return super.getMessage(); } StringBuffer expected = new StringBuffer(); int maxSize = 0; for (int i = 0; i < expectedTokenSequences.length; i++) { if (maxSize < expectedTokenSequences[i].length) { maxSize = expectedTokenSequences[i].length; } for (int j = 0; j < expectedTokenSequences[i].length; j++) { expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" "); } if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { expected.append("..."); } expected.append(eol).append(" "); } String retval = "Encountered \""; Token tok = currentToken.next; for (int i = 0; i < maxSize; i++) { if (i != 0) retval += " "; if (tok.kind == 0) { retval += tokenImage[0]; break; } retval += add_escapes(tok.image); tok = tok.next; } retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; retval += "." + eol; if (expectedTokenSequences.length == 1) { retval += "Was expecting:" + eol + " "; } else { retval += "Was expecting one of:" + eol + " "; } retval += expected.toString(); return retval; } /** * The end of line string for this machine. */ protected String eol = System.getProperty("line.separator", "\n"); /** * Used to convert raw characters to their escaped version * when these raw version cannot be used as part of an ASCII * string literal. */ protected String add_escapes(String str) { StringBuffer retval = new StringBuffer(); char ch; for (int i = 0; i < str.length(); i++) { switch (str.charAt(i)) { case 0 : continue; case '\b': retval.append("\\b"); continue; case '\t': retval.append("\\t"); continue; case '\n': retval.append("\\n"); continue; case '\f': retval.append("\\f"); continue; case '\r': retval.append("\\r"); continue; case '\"': retval.append("\\\""); continue; case '\'': retval.append("\\\'"); continue; case '\\': retval.append("\\\\"); continue; default: if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { String s = "0000" + Integer.toString(ch, 16); retval.append("\\u" + s.substring(s.length() - 4, s.length())); } else { retval.append(ch); } continue; } } return retval.toString(); } } --- NEW FILE: Property.java --- package sidekick.property.parser.property; public class Property implements Comparable { private String key = null; private String value = null; private Location startLocation = new Location(); private Location endLocation = new Location(); public Property() { } public Property(String key, String value) { this.key = key; this.value = value; } public void setKey(String key) { this.key = key; } public String getKey() { return key; } public void setValue(String value) { this.value = value; } public String getValue() { return value; } public void setStartLocation(Location start) { startLocation = start; } public Location getStartLocation() { return startLocation; } public void setEndLocation(Location end) { endLocation = end; } public Location getEndLocation() { return endLocation; } public String toString() { String k = key == null ? "" : key; String v = value == null ? "" : value; String p = k + " = " + v; return p.equals(" = ") ? "" : p; } public int compareTo(Object o) { return toString().compareToIgnoreCase(o.toString()); } } --- NEW FILE: PropertyParserTokenManager.java --- /* Generated By:JavaCC: Do not edit this line. PropertyParserTokenManager.java */ package sidekick.property.parser.property; import java.util.*; public class PropertyParserTokenManager implements PropertyParserConstants { public java.io.PrintStream debugStream = System.out; public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } private final int jjMoveStringLiteralDfa0_0() { return jjMoveNfa_0(4, 0); } private final void jjCheckNAdd(int state) { if (jjrounds[state] != jjround) { jjstateSet[jjnewStateCnt++] = state; jjrounds[state] = jjround; } } private final void jjAddStates(int start, int end) { do { jjstateSet[jjnewStateCnt++] = jjnextStates[start]; } while (start++ != end); } private final void jjCheckNAddTwoStates(int state1, int state2) { jjCheckNAdd(state1); jjCheckNAdd(state2); } private final void jjCheckNAddStates(int start, int end) { do { jjCheckNAdd(jjnextStates[start]); } while (start++ != end); } private final void jjCheckNAddStates(int start) { jjCheckNAdd(jjnextStates[start]); jjCheckNAdd(jjnextStates[start + 1]); } static final long[] jjbitVec0 = { 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL }; static final long[] jjbitVec2 = { 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL }; private final int jjMoveNfa_0(int startState, int curPos) { int[] nextStates; int startsAt = 0; jjnewStateCnt = 20; int i = 1; jjstateSet[0] = startState; int j, kind = 0x7fffffff; for (;;) { if (++jjround == 0x7fffffff) ReInitRounds(); if (curChar < 64) { long l = 1L << curChar; MatchLoop: do { switch(jjstateSet[--i]) { case 4: if ((0xdbfffff6fffffdffL & l) != 0L) { if (kind > 6) kind = 6; jjCheckNAddStates(0, 4); } else if ((0x100000200L & l) != 0L) jjCheckNAddStates(5, 14); if ((0xa00000000L & l) != 0L) jjCheckNAddTwoStates(2, 3); else if ((0x2400L & l) != 0L) { if (kind > 1) kind = 1; jjCheckNAdd(0); } break; case 0: if ((0x2400L & l) == 0L) break; if (kind > 1) kind = 1; jjCheckNAdd(0); break; case 1: if ((0xa00000000L & l) != 0L) jjCheckNAddTwoStates(2, 3); break; case 2: if ((0xffffffffffffdbffL & l) != 0L) jjCheckNAddTwoStates(2, 3); break; case 3: if ((0x2400L & l) == 0L) break; if (kind > 4) kind = 4; jjCheckNAdd(3); break; case 5: if ((0x100000200L & l) != 0L) jjCheckNAddTwoStates(5, 6); break; case 6: if ((0x2400L & l) == 0L) break; if (kind > 2) kind = 2; jjCheckNAdd(6); break; case 7: if ((0x100000200L & l) != 0L) jjCheckNAddTwoStates(7, 1); break; case 8: if ((0x100000200L & l) != 0L) jjCheckNAddStates(15, 17); break; case 10: if ((0x2400000100000200L & l) != 0L) jjCheckNAddStates(18, 20); break; case 11: if ((0xdbfffff6fffffdffL & l) != 0L) jjCheckNAddStates(18, 20); break; case 12: if ((0x2400L & l) == 0L) break; if (kind > 5) kind = 5; jjCheckNAdd(12); break; case 13: if ((0x100000200L & l) != 0L) jjCheckNAddStates(21, 23); break; case 15: if ((0x2400000100000200L & l) == 0L) break; if (kind > 6) kind = 6; jjCheckNAddTwoStates(14, 16); break; case 16: if ((0xdbfffff6fffffdffL & l) == 0L) break; if (kind > 6) kind = 6; jjCheckNAddTwoStates(14, 16); break; case 18: if ((0x2400L & l) == 0L) break; if (kind > 3) kind = 3; jjstateSet[jjnewStateCnt++] = 18; break; case 19: if ((0xdbfffff6fffffdffL & l) == 0L) break; if (kind > 6) kind = 6; jjCheckNAddStates(0, 4); break; default : break; } } while(i != startsAt); } else if (curChar < 128) { long l = 1L << (curChar & 077); MatchLoop: do { switch(jjstateSet[--i]) { case 4: if (kind > 6) kind = 6; jjCheckNAddStates(0, 4); if (curChar == 92) jjCheckNAddStates(24, 26); break; case 2: jjAddStates(27, 28); break; case 9: if (curChar == 92) jjCheckNAdd(10); break; case 11: jjCheckNAddStates(18, 20); break; case 14: if (curChar == 92) jjCheckNAdd(15); break; case 16: if (kind > 6) kind = 6; jjCheckNAddTwoStates(14, 16); break; case 17: if (curChar == 92) jjCheckNAddStates(24, 26); break; case 19: if (kind > 6) kind = 6; jjCheckNAddStates(0, 4); break; default : break; } } while(i != startsAt); } else { int hiByte = (int)(curChar >> 8); int i1 = hiByte >> 6; long l1 = 1L << (hiByte & 077); int i2 = (curChar & 0xff) >> 6; long l2 = 1L << (curChar & 077); MatchLoop: do { switch(jjstateSet[--i]) { case 4: if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) break; if (kind > 6) kind = 6; jjCheckNAddStates(0, 4); break; case 2: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjAddStates(27, 28); break; case 11: ... [truncated message content] |