Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Do Mai 10 2007 03:16:40 CEST
file stats: LOC: 271   Methods: 8
NCLOC: 153   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
LatexMathParser.java 70,8% 68,6% 87,5% 70,3%
coverage coverage
 1    /* $Id: LatexMathParser.java,v 1.5 2007/05/10 00:37:51 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2007, Michael Meyling <mime@qedeq.org>.
 6    *
 7    * "Hilbert II" is free software; you can redistribute
 8    * it and/or modify it under the terms of the GNU General Public
 9    * License as published by the Free Software Foundation; either
 10    * version 2 of the License, or (at your option) any later version.
 11    *
 12    * This program is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15    * GNU General Public License for more details.
 16    */
 17   
 18    package org.qedeq.kernel.parser;
 19   
 20    import java.util.ArrayList;
 21    import java.util.List;
 22   
 23    import org.qedeq.kernel.trace.Trace;
 24    import org.qedeq.kernel.utility.TextInput;
 25   
 26    /*
 27    * TODO refactor
 28    *
 29    * Whitespace LaTeX form, could be eaten
 30    * \t
 31    * \r
 32    * \n
 33    * \\
 34    * \\,
 35    * &
 36    * \\\\
 37    * \\par
 38    * \\quad
 39    * \\qquad
 40    *
 41    * Separator only one allowed, before and after only whitespace is possible
 42    * ,
 43    * |
 44    * $$
 45    * Separator should be read as tokens.
 46    *
 47    * Problem: If some atom like is followed by "(" it should be taken as an
 48    * (function) operator. But if we start with readToken we don't see the "("
 49    * character.
 50    *
 51    * Problem: Could whitespace be recognized?
 52    * Translating whitespace tokens into spaces is not easy, one has to know the
 53    * end of the whitespace token.
 54    * Possible solution:
 55    * function read token (LaTeX specific)
 56    * skip real whitespace (" ", "\t", "\r", "\n")
 57    * read char
 58    * case char
 59    * "\\" read characters or numbers (check LaTeX Syntax)
 60    * "{", "}", "(", ")" are also allowed
 61    * resulting string is token
 62    * LaTeX command definition modifies above:
 63    * Die meisten LATEX-Befehle haben eines der beiden folgenden Formate: Entweder sie beginnen
 64    * mit einem Backslash (\) und haben dann einen nur aus Buchstaben bestehenden Namen, der durch
 65    * ein oder mehrere Leerzeichen oder durch ein nachfolgendes Sonderzeichen oder eine Ziffer beendet
 66    * wird; oder sie bestehen aus einem Backslash und genau einem Sonderzeichen oder einer Ziffer.
 67    * Gross- und Kleinbuchstaben haben auch in Befehlsnamen verschiedene Bedeutung. Wenn man nach
 68    * einem Befehlsnamen eine Leerstelle erhalten will, muss man "{}" zur Beendigung des Befehlsnamens
 69    * oder einen eigenen Befehl f\u00fcr die Leerstelle verwenden.
 70    */
 71   
 72    /**
 73    * Parse LaTeX term or formula data into {@link org.qedeq.kernel.parser.Term}s.
 74    *
 75    * @version $Revision: 1.5 $
 76    * @author Michael Meyling
 77    */
 78    public class LatexMathParser extends MathParser {
 79   
 80    /** Characters with special LaTeX meaning. */
 81    private static final String SPECIALCHARACTERS = "(),{}\\~%$&";
 82   
 83    /** Counter for token whitespace lines. */
 84    private int tokenWhiteSpaceLines;
 85   
 86    /**
 87    * Constructor.
 88    *
 89    * @param input Parse this input.
 90    * @param operators List of operators.
 91    */
 92  2 public LatexMathParser(final TextInput input, final List operators) {
 93  2 super(new MementoTextInput(input), operators);
 94    }
 95   
 96   
 97    /**
 98    * Constructor.
 99    *
 100    * @param buffer Parse this input.
 101    * @param operators List of operators.
 102    */
 103  0 public LatexMathParser(final StringBuffer buffer, final List operators) {
 104  0 this(new TextInput(buffer), operators);
 105    }
 106   
 107  1706 protected final String readToken() {
 108  1706 final String method = "readToken()";
 109  1706 Trace.begin(this, method);
 110  1706 StringBuffer token = new StringBuffer();
 111  1706 tokenWhiteSpaceLines = 0;
 112  1706 try {
 113  1706 do {
 114  1706 tokenWhiteSpaceLines += readPureWhitespace();
 115  1706 if (tokenWhiteSpaceLines > 1) {
 116  11 break;
 117    }
 118  1695 if (eof()) {
 119  10 if (token.length() <= 0) {
 120  10 token = null;
 121    }
 122  10 break;
 123    }
 124  1685 final int c = getChar();
 125  1685 if (Character.isDigit((char) c)) {
 126  0 token.append((char) readChar());
 127  0 if (Character.isDigit((char) getChar())) {
 128  0 continue;
 129    }
 130  0 break;
 131    }
 132  1685 if (SPECIALCHARACTERS.indexOf(c) >= 0) {
 133  50 switch (c) {
 134  0 case '&':
 135  0 case '%':
 136  0 case '~':
 137  0 case '$': // TODO mime 20060504 or break in this case?
 138  0 readChar();
 139  0 continue;
 140  29 case '\\':
 141  29 final String t = readBackslashToken();
 142  29 if (t.equals(" ") || t.equals("quad") || t.equals("qquad")) {
 143  0 continue;
 144    }
 145  29 token.append(t);
 146  29 if ('_' == getChar() || '^' == getChar()) {
 147  0 token.append((char) readChar());
 148  0 continue;
 149    }
 150  29 break;
 151  0 case '{':
 152  0 readChar();
 153  0 token.append("(");
 154  0 break;
 155  0 case '}':
 156  0 readChar();
 157  0 token.append(")");
 158  0 break;
 159  21 default:
 160  21 readChar();
 161  21 token.append((char) c);
 162  21 if ('_' == getChar() || '^' == getChar()) {
 163  0 token.append((char) readChar());
 164  0 continue;
 165    }
 166    }
 167  50 break;
 168    }
 169  1635 token.append((char) readChar());
 170  1635 if ('_' == getChar() || '^' == getChar()) {
 171  0 token.append((char) readChar());
 172  0 continue;
 173    }
 174  1635 break;
 175    /*
 176    String operator = null;
 177    markPosition();
 178    while (!eof() && (Character.isLetterOrDigit((char) getChar()) || '_' == getChar()
 179    || '^' == getChar())) {
 180    token.append((char) readChar());
 181    if (null != getOperator(token.toString())) {
 182    operator = token.toString();
 183    clearMark();
 184    markPosition();
 185    }
 186    }
 187    if (operator != null) {
 188    rewindPosition();
 189    token.setLength(0);
 190    token.append(operator);
 191    } else {
 192    clearMark();
 193    }
 194    */
 195  0 } while (!eof());
 196  1706 Trace.param(this, method, "return token", token);
 197  1706 return (token != null ? token.toString() : null);
 198    } finally {
 199  1706 Trace.end(this, method);
 200    }
 201    }
 202   
 203  29 private String readBackslashToken() {
 204  29 final String method = "readBackslashToken()";
 205  29 Trace.begin(this, method);
 206  29 if (getChar() != '\\') {
 207  0 throw new IllegalArgumentException("\\ expected");
 208    }
 209  29 readChar(); // read \
 210  29 if (eof()) {
 211  0 Trace.param(this, method, "return", null);
 212  0 Trace.end(this, method);
 213  0 return null;
 214    }
 215  29 if (!Character.isLetter((char) getChar())) {
 216  14 Trace.param(this, method, "return", (char) getChar());
 217  14 Trace.end(this, method);
 218  14 return "" + ((char) readChar());
 219    }
 220  15 final StringBuffer buffer = new StringBuffer();
 221  15 do {
 222  69 buffer.append((char) readChar());
 223  69 } while (!eof() && Character.isLetter((char) getChar()));
 224  15 Trace.param(this, method, "return", buffer.toString());
 225  15 Trace.end(this, method);
 226  15 return buffer.toString();
 227    }
 228   
 229  1706 private int readPureWhitespace() {
 230  1706 int lines = 0;
 231  1706 while (getChar() != -1 && Character.isWhitespace((char) getChar())) {
 232  1049 if ('\n' == (char) getChar()) {
 233  187 lines++;
 234    }
 235  1049 readChar();
 236    }
 237  1706 return lines;
 238    }
 239   
 240  361 protected final Operator getOperator(final String token) {
 241  361 Operator result = null;
 242  361 if (token == null) {
 243  0 return result;
 244    }
 245  361 for (int i = 0; i < getOperators().size(); i++) {
 246  13851 if (token.equals(((Operator) getOperators().get(i)).getStartSymbol())) {
 247  93 result = (Operator) getOperators().get(i);
 248  93 break;
 249    }
 250    }
 251  361 return result;
 252    }
 253   
 254  338 protected final List getOperators(final String token) {
 255  338 final List result = new ArrayList();
 256  338 if (token == null) {
 257  0 return result;
 258    }
 259  338 for (int i = 0; i < getOperators().size(); i++) {
 260  14872 if (token.equals(((Operator) getOperators().get(i)).getStartSymbol())) {
 261  73 result.add(getOperators().get(i));
 262    }
 263    }
 264  338 return result;
 265    }
 266   
 267  646 protected boolean eot(final String token) {
 268  646 return token == null || token.trim().length() == 0;
 269    }
 270   
 271    }