PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

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

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