1    	package acl2s.lib.parse;
2    	
3    	import java.util.ArrayList;
4    	
5    	import acl2s.lib.parse.obj.LispObject;
6    	
7    	
8    	public abstract class Parser {
9    		public static final char EOF = Character.MAX_VALUE;
10   		protected final IParseContext pc;
11   		
12   		public Parser(IParseContext pc) {
13   			this.pc = pc;
14   		}
15   		
16   		public abstract Object save();
17   		public abstract void restore(Object o);
18   		public abstract char peek(int n);
19   		public abstract void advance(int n);
20   		
21   		public final void skip() { advance(1); }
22   		public final char pop() { char c = peek(); skip(); return c; }
23   		public final char peek() { return peek(0); }
24   		public final char next() { skip(); return peek(); }
25   	
26   		public final IParseContext getContext() { return pc; }
27   		//public final void resetContext(ParseContext pc) { this.pc = pc; }
28   		
29   		public boolean eof() { return peek(0) == EOF; }
30   		public boolean matches(String s) {
31   			for (int i = 0; i < s.length(); i++) {
32   				if (s.charAt(i) != peek(i)) return false;
33   			}
34   			return true;
35   		}
36   		public String peekString(int n) {
37   			StringBuilder b = new StringBuilder(n);
38   			for (int i = 0; i < n; i++) {
39   				char c = peek(i);
40   				if (c != EOF) b.append(c);
41   			}
42   			return b.toString();
43   		}
44   	
45   		public void skip(boolean hspace, boolean vspace, boolean comments) throws ParseException {
46   			char c;
47   			for(;;) {
48   				switch (peek()) {
49   				case ' ':
50   				case '\t':
51   					if (hspace) {
52   						advance(1);
53   						continue;
54   					} else {
55   						return;
56   					}
57   				case '\f':
58   				case '\r':
59   				case '\n':
60   					if (vspace) {
61   						advance(1);
62   						continue;
63   					} else {
64   						return;
65   					}
66   				case ';':
67   					if (comments) {
68   						do {
69   							advance(1);
70   							c = peek();
71   						} while (c != '\n' && c != '\r' && c != EOF);
72   						continue;
73   					} else {
74   						return;
75   					}
76   				case '#':
77   					if (comments && matches("#|")) {
78   						int depth = 1;
79   						advance(2);
80   						while (!eof()) {
81   							if (matches("|#")) {
82   								depth--;
83   								advance(2);
84   								if (depth == 0) break;
85   							} else if (matches("#|")) {
86   								depth++;
87   								advance(2);
88   							} else {
89   								advance(1);
90   							}
91   						}
92   						if (eof() && depth > 0)
93   							throw new ParseException("#|-style comment unterminated.  EOF reached.");
94   						continue;
95   					} else {
96   						return; //some other # construct
97   					}
98   				default:
99   					return; // not space or comment
100  				}
101  			}
102  		}
103  		
104  		public void skip(boolean hspace, boolean vspace) {
105  			for (;;) {
106  				switch (peek()) {
107  				case ' ':
108  				case '\t':
109  					if (hspace) {
110  						advance(1);
111  						continue;
112  					} else {
113  						return;
114  					}
115  				case '\f':
116  				case '\r':
117  				case '\n':
118  					if (vspace) {
119  						advance(1);
120  						continue;
121  					}
122  				default:
123  					return;	
124  				}
125  			}
126  		}
127  		
128  		public void skipSpace() {
129  			skip(true,true);
130  		}
131  		
132  		public void skipSpaceAndComments() throws ParseException {
133  			skip(true,true,true);
134  		}
135  	
136  		public void skipToTerminator() {
137  			while (!SymOrNumFns.isTerminator(peek())) skip();
138  		}
139  		
140  		/***
141  		 * parseListOfSymbols
142  		 * 
143  		 * @param output
144  		 *            String to parse. Either "NIL" or list of symbols.
145  		 * @param result
146  		 *            ArrayList to populate with results.
147  		 * @param offset
148  		 *            Starting offset of text to replace
149  		 * @param replacementLength
150  		 *            Length of text to replace.
151  		 */
152  		public static int parseListOfSymbols(String output, ArrayList<String> results,
153  				int i) {
154  			if (output.trim().toLowerCase().startsWith("nil") || i < 0)
155  				return -1;
156  	
157  			ArrayList<String> sortList = new ArrayList<String>();
158  			int start = 0;
159  			String symb;
160  			while (i < output.length()
161  					&& (Character.isWhitespace(output.charAt(i)) || output
162  							.charAt(i) == '('))
163  				++i;
164  			start = i;
165  			while (i < output.length()) {
166  				while (i < output.length()
167  						&& Character.isWhitespace(output.charAt(i)))
168  					++i;
169  				if (i >= output.length())
170  					break;
171  				start = i;
172  				// begin |this kind of symbol|
173  				if (output.charAt(i) == '|') {
174  					++i;
175  					while (i < output.length() && output.charAt(i) != '|')
176  						++i;
177  					if (i >= output.length())
178  						break;
179  					++i;
180  					symb = output.substring(start, i);
181  					if (!results.contains(symb))
182  						sortList.add(symb); // vert bars have case sensitive
183  											// symbols. Do not lowercase
184  				} else if (output.charAt(i) == ')') { // done
185  					break;
186  				} else {
187  					// regular symbol
188  					while (i < output.length()
189  							&& !Character.isWhitespace(output.charAt(i))
190  							&& output.charAt(i) != ')')
191  						++i;
192  					if (i >= output.length())
193  						break;
Event do_not_call: "java.lang.String.toLowerCase()" implicitly uses the environment's default character set, which might lead to unexpected behavior. Consider using toLowerCase(Locale locale).
194  					symb = output.substring(start, i).toLowerCase();
195  					if (!results.contains(symb))
196  						sortList.add(symb);
197  				}
198  			}
199  			java.util.Collections.sort(sortList);
200  			results.addAll(sortList);
201  			return i;
202  		}
203  		
204  		public static void main(String[] args) {
205  			ParseContext pc = new ParseContext();
206  			pc.loadBootstrapPackages();
207  			if (args.length > 0) {
208  				pc.defltPackage = args[0];
209  			}
210  			//pc.readBase = 16;
211  			StreamParser sp = new StreamParser(pc, System.in);
212  			do {
213  				LispObject o = LispObject.robustParseFirst(sp);
214  				System.out.println("-> " + o.toString(pc));
215  				System.out.println("=> " + o.toString(null));
216  			} while (!sp.ready() || !sp.eof());
217  		}
218  	}