PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms 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. package net.imglib2.ops.parse;
  37. import java.util.ArrayList;
  38. import java.util.List;
  39. import java.util.Map;
  40. import net.imglib2.ops.operation.UnaryOperation;
  41. import net.imglib2.ops.operation.real.unary.RealAbs;
  42. import net.imglib2.ops.operation.real.unary.RealArccos;
  43. import net.imglib2.ops.operation.real.unary.RealArccosh;
  44. import net.imglib2.ops.operation.real.unary.RealArccot;
  45. import net.imglib2.ops.operation.real.unary.RealArccoth;
  46. import net.imglib2.ops.operation.real.unary.RealArccsc;
  47. import net.imglib2.ops.operation.real.unary.RealArccsch;
  48. import net.imglib2.ops.operation.real.unary.RealArcsec;
  49. import net.imglib2.ops.operation.real.unary.RealArcsech;
  50. import net.imglib2.ops.operation.real.unary.RealArcsin;
  51. import net.imglib2.ops.operation.real.unary.RealArcsinh;
  52. import net.imglib2.ops.operation.real.unary.RealArctan;
  53. import net.imglib2.ops.operation.real.unary.RealArctanh;
  54. import net.imglib2.ops.operation.real.unary.RealCeil;
  55. import net.imglib2.ops.operation.real.unary.RealCos;
  56. import net.imglib2.ops.operation.real.unary.RealCosh;
  57. import net.imglib2.ops.operation.real.unary.RealCot;
  58. import net.imglib2.ops.operation.real.unary.RealCoth;
  59. import net.imglib2.ops.operation.real.unary.RealCsc;
  60. import net.imglib2.ops.operation.real.unary.RealCsch;
  61. import net.imglib2.ops.operation.real.unary.RealCubeRoot;
  62. import net.imglib2.ops.operation.real.unary.RealExp;
  63. import net.imglib2.ops.operation.real.unary.RealExpMinusOne;
  64. import net.imglib2.ops.operation.real.unary.RealFloor;
  65. import net.imglib2.ops.operation.real.unary.RealGaussianRandom;
  66. import net.imglib2.ops.operation.real.unary.RealLog;
  67. import net.imglib2.ops.operation.real.unary.RealLog10;
  68. import net.imglib2.ops.operation.real.unary.RealLog2;
  69. import net.imglib2.ops.operation.real.unary.RealLogOnePlusX;
  70. import net.imglib2.ops.operation.real.unary.RealNearestInt;
  71. import net.imglib2.ops.operation.real.unary.RealRound;
  72. import net.imglib2.ops.operation.real.unary.RealSec;
  73. import net.imglib2.ops.operation.real.unary.RealSech;
  74. import net.imglib2.ops.operation.real.unary.RealSignum;
  75. import net.imglib2.ops.operation.real.unary.RealSin;
  76. import net.imglib2.ops.operation.real.unary.RealSinc;
  77. import net.imglib2.ops.operation.real.unary.RealSincPi;
  78. import net.imglib2.ops.operation.real.unary.RealSinh;
  79. import net.imglib2.ops.operation.real.unary.RealSqr;
  80. import net.imglib2.ops.operation.real.unary.RealSqrt;
  81. import net.imglib2.ops.operation.real.unary.RealStep;
  82. import net.imglib2.ops.operation.real.unary.RealTan;
  83. import net.imglib2.ops.operation.real.unary.RealTanh;
  84. import net.imglib2.ops.operation.real.unary.RealUlp;
  85. import net.imglib2.ops.operation.real.unary.RealUniformRandom;
  86. import net.imglib2.ops.parse.token.And;
  87. import net.imglib2.ops.parse.token.AngleReference;
  88. import net.imglib2.ops.parse.token.Assign;
  89. import net.imglib2.ops.parse.token.CloseParen;
  90. import net.imglib2.ops.parse.token.CloseRange;
  91. import net.imglib2.ops.parse.token.Comma;
  92. import net.imglib2.ops.parse.token.DimensionReference;
  93. import net.imglib2.ops.parse.token.DistanceFromCenterReference;
  94. import net.imglib2.ops.parse.token.Divide;
  95. import net.imglib2.ops.parse.token.DotDot;
  96. import net.imglib2.ops.parse.token.Equal;
  97. import net.imglib2.ops.parse.token.Exponent;
  98. import net.imglib2.ops.parse.token.FunctionCall;
  99. import net.imglib2.ops.parse.token.Greater;
  100. import net.imglib2.ops.parse.token.GreaterEqual;
  101. import net.imglib2.ops.parse.token.ImgReference;
  102. import net.imglib2.ops.parse.token.Int;
  103. import net.imglib2.ops.parse.token.Less;
  104. import net.imglib2.ops.parse.token.LessEqual;
  105. import net.imglib2.ops.parse.token.Max;
  106. import net.imglib2.ops.parse.token.Min;
  107. import net.imglib2.ops.parse.token.Minus;
  108. import net.imglib2.ops.parse.token.Mod;
  109. import net.imglib2.ops.parse.token.Not;
  110. import net.imglib2.ops.parse.token.NotEqual;
  111. import net.imglib2.ops.parse.token.OpenParen;
  112. import net.imglib2.ops.parse.token.OpenRange;
  113. import net.imglib2.ops.parse.token.Or;
  114. import net.imglib2.ops.parse.token.Plus;
  115. import net.imglib2.ops.parse.token.Real;
  116. import net.imglib2.ops.parse.token.Times;
  117. import net.imglib2.ops.parse.token.Token;
  118. import net.imglib2.ops.parse.token.TypeBoundReference;
  119. import net.imglib2.ops.parse.token.Variable;
  120. import net.imglib2.ops.parse.token.Xor;
  121. import net.imglib2.type.numeric.real.DoubleType;
  122. /**
  123. * Responsible for turning a input String in the equation language into a set
  124. * of tokens for use later by a parser.
  125. *
  126. * @author Barry DeZonia
  127. *
  128. */
  129. public class Lexer {
  130. // -- constructor --
  131. public Lexer() {}
  132. // -- Lexer methods --
  133. public ParseStatus tokenize(String spec, Map<String,Integer> varMap)
  134. {
  135. List<Token> tokens = new ArrayList<Token>();
  136. char[] chars = spec.toCharArray();
  137. int i = 0;
  138. while (i < chars.length) {
  139. Character ch = chars[i];
  140. if (Character.isLetter(ch)) {
  141. StringBuilder builder = new StringBuilder();
  142. while (i < chars.length &&
  143. (Character.isLetter(chars[i]) ||
  144. Character.isDigit(chars[i])))
  145. {
  146. builder.append(chars[i]);
  147. i++;
  148. }
  149. String name = builder.toString();
  150. Token token = reservedWordLookup(name, i);
  151. if (token != null)
  152. tokens.add(token);
  153. else
  154. tokens.add(new Variable(i, name, varMap));
  155. }
  156. else if (Character.isDigit(ch)) {
  157. int start = i;
  158. StringBuilder builder = new StringBuilder();
  159. boolean isReal = false;
  160. while (i < chars.length && (Character.isDigit(chars[i]))) {
  161. builder.append(chars[i]);
  162. i++;
  163. char next = (i < chars.length) ? chars[i] : 0;
  164. char next2 = (i < chars.length-1) ? chars[i+1] : 0;
  165. if ((next == '.') && (next2 == '.')) break;
  166. if (next == '.') {
  167. if (isReal) // already seen a decimal
  168. return lexicalError(spec, i, chars[i]);
  169. // else valid decimal
  170. isReal = true;
  171. builder.append(".");
  172. i++;
  173. }
  174. }
  175. String numStr = builder.toString();
  176. if (isReal)
  177. tokens.add(new Real(start, numStr));
  178. else
  179. tokens.add(new Int(start, numStr));
  180. }
  181. else if (ch == '<') {
  182. i++;
  183. if (i < chars.length && chars[i] == '=') {
  184. i++;
  185. tokens.add(new LessEqual(i-2, "<="));
  186. }
  187. else
  188. tokens.add(new Less(i-1, "<"));
  189. }
  190. else if (ch == '>') {
  191. i++;
  192. if (i < chars.length && chars[i] == '=') {
  193. i++;
  194. tokens.add(new GreaterEqual(i-2, ">="));
  195. }
  196. else
  197. tokens.add(new Greater(i-1, ">"));
  198. }
  199. else if (ch == '!') {
  200. i++;
  201. if (i < chars.length && chars[i] == '=') {
  202. i++;
  203. tokens.add(new NotEqual(i-2, "!="));
  204. }
  205. else
  206. tokens.add(new Not(i-1, "!"));
  207. }
  208. else if (ch == '=') {
  209. i++;
  210. if (i < chars.length && chars[i] == '=') {
  211. i++;
  212. tokens.add(new Equal(i-2, "=="));
  213. }
  214. else
  215. tokens.add(new Assign(i-1, "="));
  216. }
  217. else if (ch == '.') {
  218. i++;
  219. if (i < chars.length && chars[i] == '.') {
  220. i++;
  221. tokens.add(new DotDot(i-2, ".."));
  222. }
  223. else
  224. return lexicalError(spec, i-1, ch);
  225. }
  226. else if (ch == '&') {
  227. i++;
  228. if (i < chars.length && chars[i] == '&') {
  229. i++;
  230. tokens.add(new And(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 Or(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 Xor(i-2, "^^"));
  249. }
  250. else
  251. tokens.add(new Exponent(i-1, "^"));
  252. }
  253. else if (ch == ',') {
  254. i++;
  255. tokens.add(new Comma(i-1, ","));
  256. }
  257. else if (ch == '[') {
  258. i++;
  259. tokens.add(new OpenRange(i-1, "["));
  260. }
  261. else if (ch == ']') {
  262. i++;
  263. tokens.add(new CloseRange(i-1, "["));
  264. }
  265. else if (ch == '+') {
  266. i++;
  267. tokens.add(new Plus(i-1, "+"));
  268. }
  269. else if (ch == '*') {
  270. i++;
  271. tokens.add(new Times(i-1, "*"));
  272. }
  273. else if (ch == '/') {
  274. i++;
  275. tokens.add(new Divide(i-1, "/"));
  276. }
  277. else if (ch == '-') {
  278. i++;
  279. tokens.add(new Minus(i-1, "-"));
  280. }
  281. else if (ch == '%') {
  282. i++;
  283. tokens.add(new Mod(i-1, "%"));
  284. }
  285. else if (ch == '(') {
  286. i++;
  287. tokens.add(new OpenParen(i-1, "("));
  288. }
  289. else if (ch == ')') {
  290. i++;
  291. tokens.add(new CloseParen(i-1, ")"));
  292. }
  293. else if (Character.isWhitespace(ch))
  294. i++;
  295. else { // invalid char
  296. return lexicalError(spec, i, ch);
  297. }
  298. }
  299. ParseStatus status = new ParseStatus();
  300. status.tokens = tokens;
  301. return status;
  302. }
  303. // -- private helpers --
  304. private Token reservedWordLookup(String name, int pos) {
  305. // constants
  306. if (name.equals("E")) return new Real(pos, name, Math.E);
  307. if (name.equals("PI")) return new Real(pos, name, Math.PI);
  308. // image reference
  309. if (name.equals("img")) return new ImgReference(pos, name);
  310. // dimension reference
  311. if (name.equals("dim")) return new DimensionReference(pos, name);
  312. // type bound reference
  313. if (name.equals("tmin")) return new TypeBoundReference(pos, name, true);
  314. if (name.equals("tmax")) return new TypeBoundReference(pos, name, false);
  315. // distance from center reference
  316. if (name.equals("dctr")) return new DistanceFromCenterReference(pos, name);
  317. // angle reference
  318. if (name.equals("angle")) return new AngleReference(pos, name);
  319. // min/max call
  320. if (name.equals("min")) return new Min(pos, name);
  321. if (name.equals("max")) return new Max(pos, name);
  322. // logical operations
  323. if (name.equals("and")) return new And(pos, name);
  324. if (name.equals("or")) return new Or(pos, name);
  325. if (name.equals("xor")) return new Xor(pos, name);
  326. if (name.equals("not")) return new Not(pos, name);
  327. // predefined functions
  328. UnaryOperation<DoubleType, DoubleType> op = null;
  329. if (name.equals("abs")) op = new RealAbs<DoubleType,DoubleType>();
  330. if (name.equals("acos")) op = new RealArccos<DoubleType,DoubleType>();
  331. if (name.equals("acosh")) op = new RealArccosh<DoubleType,DoubleType>();
  332. if (name.equals("acot")) op = new RealArccot<DoubleType,DoubleType>();
  333. if (name.equals("acoth")) op = new RealArccoth<DoubleType,DoubleType>();
  334. if (name.equals("acsc")) op = new RealArccsc<DoubleType,DoubleType>();
  335. if (name.equals("acsch")) op = new RealArccsch<DoubleType,DoubleType>();
  336. if (name.equals("asec")) op = new RealArcsec<DoubleType,DoubleType>();
  337. if (name.equals("asech")) op = new RealArcsech<DoubleType,DoubleType>();
  338. if (name.equals("asin")) op = new RealArcsin<DoubleType,DoubleType>();
  339. if (name.equals("asinh")) op = new RealArcsinh<DoubleType,DoubleType>();
  340. if (name.equals("atan")) op = new RealArctan<DoubleType,DoubleType>();
  341. if (name.equals("atanh")) op = new RealArctanh<DoubleType,DoubleType>();
  342. if (name.equals("cbrt")) op = new RealCubeRoot<DoubleType,DoubleType>();
  343. if (name.equals("ceil")) op = new RealCeil<DoubleType,DoubleType>();
  344. if (name.equals("cos")) op = new RealCos<DoubleType,DoubleType>();
  345. if (name.equals("cosh")) op = new RealCosh<DoubleType,DoubleType>();
  346. if (name.equals("cot")) op = new RealCot<DoubleType,DoubleType>();
  347. if (name.equals("coth")) op = new RealCoth<DoubleType,DoubleType>();
  348. if (name.equals("csc")) op = new RealCsc<DoubleType,DoubleType>();
  349. if (name.equals("csch")) op = new RealCsch<DoubleType,DoubleType>();
  350. if (name.equals("exp")) op = new RealExp<DoubleType,DoubleType>();
  351. if (name.equals("expm1")) op = new RealExpMinusOne<DoubleType,DoubleType>();
  352. if (name.equals("floor")) op = new RealFloor<DoubleType,DoubleType>();
  353. if (name.equals("gauss")) op = new RealGaussianRandom<DoubleType,DoubleType>();
  354. if (name.equals("log")) op = new RealLog<DoubleType,DoubleType>();
  355. if (name.equals("log1p")) op = new RealLogOnePlusX<DoubleType,DoubleType>();
  356. if (name.equals("log10")) op = new RealLog10<DoubleType,DoubleType>();
  357. if (name.equals("log2")) op = new RealLog2<DoubleType,DoubleType>();
  358. if (name.equals("rand")) op = new RealUniformRandom<DoubleType,DoubleType>();
  359. if (name.equals("rint")) op = new RealNearestInt<DoubleType,DoubleType>();
  360. if (name.equals("round")) op = new RealRound<DoubleType,DoubleType>();
  361. if (name.equals("sec")) op = new RealSec<DoubleType,DoubleType>();
  362. if (name.equals("sech")) op = new RealSech<DoubleType,DoubleType>();
  363. if (name.equals("signum")) op = new RealSignum<DoubleType,DoubleType>();
  364. if (name.equals("sin")) op = new RealSin<DoubleType,DoubleType>();
  365. if (name.equals("sinc")) op = new RealSinc<DoubleType,DoubleType>();
  366. if (name.equals("sincpi")) op = new RealSincPi<DoubleType,DoubleType>();
  367. if (name.equals("sinh")) op = new RealSinh<DoubleType,DoubleType>();
  368. if (name.equals("sqr")) op = new RealSqr<DoubleType,DoubleType>();
  369. if (name.equals("sqrt")) op = new RealSqrt<DoubleType,DoubleType>();
  370. if (name.equals("step")) op = new RealStep<DoubleType,DoubleType>();
  371. if (name.equals("tan")) op = new RealTan<DoubleType,DoubleType>();
  372. if (name.equals("tanh")) op = new RealTanh<DoubleType,DoubleType>();
  373. if (name.equals("ulp")) op = new RealUlp<DoubleType,DoubleType>();
  374. if (op != null) return new FunctionCall(pos, name, op);
  375. return null;
  376. }
  377. private ParseStatus lexicalError(String input, int pos, Character ch) {
  378. List<Token> emptyTokenList = new ArrayList<Token>();
  379. String errorMessage = "Invalid char ("+ch+") at position ("+pos+") of input string ("+input+")";
  380. ParseStatus status = new ParseStatus();
  381. status.tokens = emptyTokenList;
  382. status.columnNumber = pos;
  383. status.errMsg = errorMessage;
  384. return status;
  385. }
  386. }