PageRenderTime 548ms CodeModel.GetById 161ms app.highlight 182ms RepoModel.GetById 200ms app.codeStats 0ms

/IJ_Mobile/src/net/imglib2/ops/parse/Lexer.java

https://github.com/msteptoe/FURI_Code
Java | 409 lines | 331 code | 23 blank | 55 comment | 159 complexity | 9f1425eafe6bde0d259fa87996fc4553 MD5 | raw file
  1/*
  2 * #%L
  3 * ImgLib2: a general-purpose, multidimensional image processing library.
  4 * %%
  5 * Copyright (C) 2009 - 2012 Stephan Preibisch, Stephan Saalfeld, Tobias
  6 * Pietzsch, Albert Cardona, Barry DeZonia, Curtis Rueden, Lee Kamentsky, Larry
  7 * Lindsey, Johannes Schindelin, Christian Dietz, Grant Harris, Jean-Yves
  8 * Tinevez, Steffen Jaensch, Mark Longair, Nick Perry, and Jan Funke.
  9 * %%
 10 * Redistribution and use in source and binary forms, with or without
 11 * modification, are permitted provided that the following conditions are met:
 12 * 
 13 * 1. Redistributions of source code must retain the above copyright notice,
 14 *    this list of conditions and the following disclaimer.
 15 * 2. Redistributions in binary form must reproduce the above copyright notice,
 16 *    this list of conditions and the following disclaimer in the documentation
 17 *    and/or other materials provided with the distribution.
 18 * 
 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 29 * POSSIBILITY OF SUCH DAMAGE.
 30 * 
 31 * The views and conclusions contained in the software and documentation are
 32 * those of the authors and should not be interpreted as representing official
 33 * policies, either expressed or implied, of any organization.
 34 * #L%
 35 */
 36
 37
 38package net.imglib2.ops.parse;
 39
 40import java.util.ArrayList;
 41import java.util.List;
 42import java.util.Map;
 43
 44import net.imglib2.ops.operation.UnaryOperation;
 45import net.imglib2.ops.operation.real.unary.RealAbs;
 46import net.imglib2.ops.operation.real.unary.RealArccos;
 47import net.imglib2.ops.operation.real.unary.RealArccosh;
 48import net.imglib2.ops.operation.real.unary.RealArccot;
 49import net.imglib2.ops.operation.real.unary.RealArccoth;
 50import net.imglib2.ops.operation.real.unary.RealArccsc;
 51import net.imglib2.ops.operation.real.unary.RealArccsch;
 52import net.imglib2.ops.operation.real.unary.RealArcsec;
 53import net.imglib2.ops.operation.real.unary.RealArcsech;
 54import net.imglib2.ops.operation.real.unary.RealArcsin;
 55import net.imglib2.ops.operation.real.unary.RealArcsinh;
 56import net.imglib2.ops.operation.real.unary.RealArctan;
 57import net.imglib2.ops.operation.real.unary.RealArctanh;
 58import net.imglib2.ops.operation.real.unary.RealCeil;
 59import net.imglib2.ops.operation.real.unary.RealCos;
 60import net.imglib2.ops.operation.real.unary.RealCosh;
 61import net.imglib2.ops.operation.real.unary.RealCot;
 62import net.imglib2.ops.operation.real.unary.RealCoth;
 63import net.imglib2.ops.operation.real.unary.RealCsc;
 64import net.imglib2.ops.operation.real.unary.RealCsch;
 65import net.imglib2.ops.operation.real.unary.RealCubeRoot;
 66import net.imglib2.ops.operation.real.unary.RealExp;
 67import net.imglib2.ops.operation.real.unary.RealExpMinusOne;
 68import net.imglib2.ops.operation.real.unary.RealFloor;
 69import net.imglib2.ops.operation.real.unary.RealGaussianRandom;
 70import net.imglib2.ops.operation.real.unary.RealLog;
 71import net.imglib2.ops.operation.real.unary.RealLog10;
 72import net.imglib2.ops.operation.real.unary.RealLog2;
 73import net.imglib2.ops.operation.real.unary.RealLogOnePlusX;
 74import net.imglib2.ops.operation.real.unary.RealNearestInt;
 75import net.imglib2.ops.operation.real.unary.RealRound;
 76import net.imglib2.ops.operation.real.unary.RealSec;
 77import net.imglib2.ops.operation.real.unary.RealSech;
 78import net.imglib2.ops.operation.real.unary.RealSignum;
 79import net.imglib2.ops.operation.real.unary.RealSin;
 80import net.imglib2.ops.operation.real.unary.RealSinc;
 81import net.imglib2.ops.operation.real.unary.RealSincPi;
 82import net.imglib2.ops.operation.real.unary.RealSinh;
 83import net.imglib2.ops.operation.real.unary.RealSqr;
 84import net.imglib2.ops.operation.real.unary.RealSqrt;
 85import net.imglib2.ops.operation.real.unary.RealStep;
 86import net.imglib2.ops.operation.real.unary.RealTan;
 87import net.imglib2.ops.operation.real.unary.RealTanh;
 88import net.imglib2.ops.operation.real.unary.RealUlp;
 89import net.imglib2.ops.operation.real.unary.RealUniformRandom;
 90import net.imglib2.ops.parse.token.And;
 91import net.imglib2.ops.parse.token.AngleReference;
 92import net.imglib2.ops.parse.token.Assign;
 93import net.imglib2.ops.parse.token.CloseParen;
 94import net.imglib2.ops.parse.token.CloseRange;
 95import net.imglib2.ops.parse.token.Comma;
 96import net.imglib2.ops.parse.token.DimensionReference;
 97import net.imglib2.ops.parse.token.DistanceFromCenterReference;
 98import net.imglib2.ops.parse.token.Divide;
 99import net.imglib2.ops.parse.token.DotDot;
100import net.imglib2.ops.parse.token.Equal;
101import net.imglib2.ops.parse.token.Exponent;
102import net.imglib2.ops.parse.token.FunctionCall;
103import net.imglib2.ops.parse.token.Greater;
104import net.imglib2.ops.parse.token.GreaterEqual;
105import net.imglib2.ops.parse.token.ImgReference;
106import net.imglib2.ops.parse.token.Int;
107import net.imglib2.ops.parse.token.Less;
108import net.imglib2.ops.parse.token.LessEqual;
109import net.imglib2.ops.parse.token.Max;
110import net.imglib2.ops.parse.token.Min;
111import net.imglib2.ops.parse.token.Minus;
112import net.imglib2.ops.parse.token.Mod;
113import net.imglib2.ops.parse.token.Not;
114import net.imglib2.ops.parse.token.NotEqual;
115import net.imglib2.ops.parse.token.OpenParen;
116import net.imglib2.ops.parse.token.OpenRange;
117import net.imglib2.ops.parse.token.Or;
118import net.imglib2.ops.parse.token.Plus;
119import net.imglib2.ops.parse.token.Real;
120import net.imglib2.ops.parse.token.Times;
121import net.imglib2.ops.parse.token.Token;
122import net.imglib2.ops.parse.token.TypeBoundReference;
123import net.imglib2.ops.parse.token.Variable;
124import net.imglib2.ops.parse.token.Xor;
125import net.imglib2.type.numeric.real.DoubleType;
126
127/**
128* Responsible for turning a input String in the equation language into a set
129* of tokens for use later by a parser.
130* 
131* @author Barry DeZonia
132*
133*/
134public class Lexer {
135
136	// -- constructor --
137	
138	public Lexer() {}
139	
140	// -- Lexer methods --
141	
142	public ParseStatus tokenize(String spec, Map<String,Integer> varMap)
143	{
144		List<Token> tokens = new ArrayList<Token>();
145		char[] chars = spec.toCharArray();
146		int i = 0;
147		while (i < chars.length) {
148			Character ch = chars[i];
149			if (Character.isLetter(ch)) {
150				StringBuilder builder = new StringBuilder();
151				while (i < chars.length &&
152						(Character.isLetter(chars[i]) ||
153							Character.isDigit(chars[i])))
154				{
155					builder.append(chars[i]);
156					i++;
157				}
158				String name = builder.toString();
159				Token token = reservedWordLookup(name, i);
160				if (token != null)
161					tokens.add(token);
162				else
163					tokens.add(new Variable(i, name, varMap));
164			}
165			else if (Character.isDigit(ch)) {
166				int start = i;
167				StringBuilder builder = new StringBuilder();
168				boolean isReal = false;
169				while (i < chars.length && (Character.isDigit(chars[i]))) {
170					builder.append(chars[i]);
171					i++;
172					char next = (i < chars.length) ? chars[i] : 0;
173					char next2 = (i < chars.length-1) ? chars[i+1] : 0;
174					if ((next == '.') && (next2 == '.')) break;
175					if (next == '.') {
176						if (isReal) // already seen a decimal
177							return lexicalError(spec, i, chars[i]);
178						// else valid decimal
179						isReal = true;
180						builder.append(".");
181						i++;
182					}
183				}
184				String numStr = builder.toString();
185				if (isReal)
186					tokens.add(new Real(start, numStr));
187				else
188					tokens.add(new Int(start, numStr));
189			}
190			else if (ch == '<') {
191				i++;
192				if (i < chars.length && chars[i] == '=') {
193					i++;
194					tokens.add(new LessEqual(i-2, "<="));
195				}
196				else
197					tokens.add(new Less(i-1, "<"));
198			}
199			else if (ch == '>') {
200				i++;
201				if (i < chars.length && chars[i] == '=') {
202					i++;
203					tokens.add(new GreaterEqual(i-2, ">="));
204				}
205				else
206					tokens.add(new Greater(i-1, ">"));
207			}
208			else if (ch == '!') {
209				i++;
210				if (i < chars.length && chars[i] == '=') {
211					i++;
212					tokens.add(new NotEqual(i-2, "!="));
213				}
214				else
215					tokens.add(new Not(i-1, "!"));
216			}
217			else if (ch == '=') {
218				i++;
219				if (i < chars.length && chars[i] == '=') {
220					i++;
221					tokens.add(new Equal(i-2, "=="));
222				}
223				else
224					tokens.add(new Assign(i-1, "="));
225			}
226			else if (ch == '.') {
227				i++;
228				if (i < chars.length && chars[i] == '.') {
229					i++;
230					tokens.add(new DotDot(i-2, ".."));
231				}
232				else
233					return lexicalError(spec, i-1, ch);
234			}
235			else if (ch == '&') {
236				i++;
237				if (i < chars.length && chars[i] == '&') {
238					i++;
239					tokens.add(new And(i-2, "&&"));
240				}
241				else
242					return lexicalError(spec, i-1, ch);
243			}
244			else if (ch == '|') {
245				i++;
246				if (i < chars.length && chars[i] == '|') {
247					i++;
248					tokens.add(new Or(i-2, "||"));
249				}
250				else
251					return lexicalError(spec, i-1, ch);
252			}
253			else if (ch == '^') {
254				i++;
255				if (i < chars.length && chars[i] == '^') {
256					i++;
257					tokens.add(new Xor(i-2, "^^"));
258				}
259				else
260					tokens.add(new Exponent(i-1, "^"));
261			}
262			else if (ch == ',') {
263				i++;
264				tokens.add(new Comma(i-1, ","));
265			}
266			else if (ch == '[') {
267				i++;
268				tokens.add(new OpenRange(i-1, "["));
269			}
270			else if (ch == ']') {
271				i++;
272				tokens.add(new CloseRange(i-1, "["));
273			}
274			else if (ch == '+') {
275				i++;
276				tokens.add(new Plus(i-1, "+"));
277			}
278			else if (ch == '*') {
279				i++;
280				tokens.add(new Times(i-1, "*"));
281			}
282			else if (ch == '/') {
283				i++;
284				tokens.add(new Divide(i-1, "/"));
285			}
286			else if (ch == '-') {
287				i++;
288				tokens.add(new Minus(i-1, "-"));
289			}
290			else if (ch == '%') {
291				i++;
292				tokens.add(new Mod(i-1, "%"));
293			}
294			else if (ch == '(') {
295				i++;
296				tokens.add(new OpenParen(i-1, "("));
297			}
298			else if (ch == ')') {
299				i++;
300				tokens.add(new CloseParen(i-1, ")"));
301			}
302			else if (Character.isWhitespace(ch))
303				i++;
304			else { // invalid char
305				return lexicalError(spec, i, ch);
306			}
307		}
308		ParseStatus status = new ParseStatus();
309		status.tokens = tokens;
310		return status;
311	}
312
313	// -- private helpers --
314	
315	private Token reservedWordLookup(String name, int pos) {
316		// constants
317		if (name.equals("E")) return new Real(pos, name, Math.E);
318		if (name.equals("PI")) return new Real(pos, name, Math.PI);
319
320		// image reference
321		if (name.equals("img")) return new ImgReference(pos, name);
322		
323		// dimension reference
324		if (name.equals("dim")) return new DimensionReference(pos, name);
325		
326		// type bound reference
327		if (name.equals("tmin")) return new TypeBoundReference(pos, name, true);
328		if (name.equals("tmax")) return new TypeBoundReference(pos, name, false);
329		
330		// distance from center reference
331		if (name.equals("dctr")) return new DistanceFromCenterReference(pos, name);
332
333		// angle reference
334		if (name.equals("angle")) return new AngleReference(pos, name);
335		
336		// min/max call
337		if (name.equals("min")) return new Min(pos, name);
338		if (name.equals("max")) return new Max(pos, name);
339		
340		// logical operations
341		if (name.equals("and")) return new And(pos, name);
342		if (name.equals("or")) return new Or(pos, name);
343		if (name.equals("xor")) return new Xor(pos, name);
344		if (name.equals("not")) return new Not(pos, name);
345
346		// predefined functions
347		UnaryOperation<DoubleType, DoubleType> op = null;
348
349		if (name.equals("abs")) op = new RealAbs<DoubleType,DoubleType>();
350		if (name.equals("acos")) op = new RealArccos<DoubleType,DoubleType>();
351		if (name.equals("acosh")) op = new RealArccosh<DoubleType,DoubleType>();
352		if (name.equals("acot")) op = new RealArccot<DoubleType,DoubleType>();
353		if (name.equals("acoth")) op = new RealArccoth<DoubleType,DoubleType>();
354		if (name.equals("acsc")) op = new RealArccsc<DoubleType,DoubleType>();
355		if (name.equals("acsch")) op = new RealArccsch<DoubleType,DoubleType>();
356		if (name.equals("asec")) op = new RealArcsec<DoubleType,DoubleType>();
357		if (name.equals("asech")) op = new RealArcsech<DoubleType,DoubleType>();
358		if (name.equals("asin")) op = new RealArcsin<DoubleType,DoubleType>();
359		if (name.equals("asinh")) op = new RealArcsinh<DoubleType,DoubleType>();
360		if (name.equals("atan")) op = new RealArctan<DoubleType,DoubleType>();
361		if (name.equals("atanh")) op = new RealArctanh<DoubleType,DoubleType>();
362		if (name.equals("cbrt")) op = new RealCubeRoot<DoubleType,DoubleType>();
363		if (name.equals("ceil")) op = new RealCeil<DoubleType,DoubleType>();
364		if (name.equals("cos")) op = new RealCos<DoubleType,DoubleType>();
365		if (name.equals("cosh")) op = new RealCosh<DoubleType,DoubleType>();
366		if (name.equals("cot")) op = new RealCot<DoubleType,DoubleType>();
367		if (name.equals("coth")) op = new RealCoth<DoubleType,DoubleType>();
368		if (name.equals("csc")) op = new RealCsc<DoubleType,DoubleType>();
369		if (name.equals("csch")) op = new RealCsch<DoubleType,DoubleType>();
370		if (name.equals("exp")) op = new RealExp<DoubleType,DoubleType>();
371		if (name.equals("expm1")) op = new RealExpMinusOne<DoubleType,DoubleType>();
372		if (name.equals("floor")) op = new RealFloor<DoubleType,DoubleType>();
373		if (name.equals("gauss")) op = new RealGaussianRandom<DoubleType,DoubleType>();
374		if (name.equals("log")) op = new RealLog<DoubleType,DoubleType>();
375		if (name.equals("log1p")) op = new RealLogOnePlusX<DoubleType,DoubleType>();
376		if (name.equals("log10")) op = new RealLog10<DoubleType,DoubleType>();
377		if (name.equals("log2")) op = new RealLog2<DoubleType,DoubleType>();
378		if (name.equals("rand")) op = new RealUniformRandom<DoubleType,DoubleType>();
379		if (name.equals("rint")) op = new RealNearestInt<DoubleType,DoubleType>();
380		if (name.equals("round")) op = new RealRound<DoubleType,DoubleType>();
381		if (name.equals("sec")) op = new RealSec<DoubleType,DoubleType>();
382		if (name.equals("sech")) op = new RealSech<DoubleType,DoubleType>();
383		if (name.equals("signum")) op = new RealSignum<DoubleType,DoubleType>();
384		if (name.equals("sin")) op = new RealSin<DoubleType,DoubleType>();
385		if (name.equals("sinc")) op = new RealSinc<DoubleType,DoubleType>();
386		if (name.equals("sincpi")) op = new RealSincPi<DoubleType,DoubleType>();
387		if (name.equals("sinh")) op = new RealSinh<DoubleType,DoubleType>();
388		if (name.equals("sqr")) op = new RealSqr<DoubleType,DoubleType>();
389		if (name.equals("sqrt")) op = new RealSqrt<DoubleType,DoubleType>();
390		if (name.equals("step")) op = new RealStep<DoubleType,DoubleType>();
391		if (name.equals("tan")) op = new RealTan<DoubleType,DoubleType>();
392		if (name.equals("tanh")) op = new RealTanh<DoubleType,DoubleType>();
393		if (name.equals("ulp")) op = new RealUlp<DoubleType,DoubleType>();
394		
395		if (op != null) return new FunctionCall(pos, name, op);
396		
397		return null;
398	}
399	
400	private ParseStatus lexicalError(String input, int pos, Character ch) {
401		List<Token> emptyTokenList = new ArrayList<Token>();
402		String errorMessage = "Invalid char ("+ch+") at position ("+pos+") of input string ("+input+")";
403		ParseStatus status = new ParseStatus();
404		status.tokens = emptyTokenList;
405		status.columnNumber = pos;
406		status.errMsg = errorMessage;
407		return status;
408	}
409}