Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Sa Dez 22 2007 01:35:21 CET
file stats: LOC: 271   Methods: 8
NCLOC: 153   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
LatexMathParser.java 83,3% 78,4% 87,5% 80,4%
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  17 public LatexMathParser(final TextInput input, final List operators) {
 93  17 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  3074 protected final String readToken() {
 108  3074 final String method = "readToken()";
 109  3074 Trace.begin(this, method);
 110  3074 StringBuffer token = new StringBuffer();
 111  3074 tokenWhiteSpaceLines = 0;
 112  3074 try {
 113  3074 do {
 114  3260 tokenWhiteSpaceLines += readPureWhitespace();
 115  3260 if (tokenWhiteSpaceLines > 1) {
 116  21 break;
 117    }
 118  3239 if (eof()) {
 119  54 if (token.length() <= 0) {
 120  54 token = null;
 121    }
 122  54 break;
 123    }
 124  3185 final int c = getChar();
 125  3185 if (Character.isDigit((char) c)) {
 126  16 token.append((char) readChar());
 127  16 if (Character.isDigit((char) getChar())) {
 128  0 continue;
 129    }
 130  16 break;
 131    }
 132  3169 if (SPECIALCHARACTERS.indexOf(c) >= 0) {
 133  1047 switch (c) {
 134  0 case '&':
 135  0 case '%':
 136  22 case '~':
 137  134 case '$': // TODO mime 20060504 or break in this case?
 138  156 readChar();
 139  156 continue;
 140  294 case '\\':
 141  294 final String t = readBackslashToken();
 142  294 if (t.equals(" ") || t.equals("quad") || t.equals("qquad")) {
 143  34 continue;
 144    }
 145  260 token.append(t);
 146  260 if ('_' == getChar() || '^' == getChar()) {
 147  0 token.append((char) readChar());
 148  0 continue;
 149    }
 150  260 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  597 default:
 160  597 readChar();
 161  597 token.append((char) c);
 162  597 if ('_' == getChar() || '^' == getChar()) {
 163  0 token.append((char) readChar());
 164  0 continue;
 165    }
 166    }
 167  857 break;
 168    }
 169  2122 token.append((char) readChar());
 170  2122 if ('_' == getChar() || '^' == getChar()) {
 171  16 token.append((char) readChar());
 172  16 continue;
 173    }
 174  2106 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  206 } while (!eof());
 196  3074 Trace.param(this, method, "return token", token);
 197  3074 return (token != null ? token.toString() : null);
 198    } finally {
 199  3074 Trace.end(this, method);
 200    }
 201    }
 202   
 203  294 private String readBackslashToken() {
 204  294 final String method = "readBackslashToken()";
 205  294 Trace.begin(this, method);
 206  294 if (getChar() != '\\') {
 207  0 throw new IllegalArgumentException("\\ expected");
 208    }
 209  294 readChar(); // read \
 210  294 if (eof()) {
 211  0 Trace.param(this, method, "return", null);
 212  0 Trace.end(this, method);
 213  0 return null;
 214    }
 215  294 if (!Character.isLetter((char) getChar())) {
 216  58 Trace.param(this, method, "return", (char) getChar());
 217  58 Trace.end(this, method);
 218  58 return "" + ((char) readChar());
 219    }
 220  236 final StringBuffer buffer = new StringBuffer();
 221  236 do {
 222  980 buffer.append((char) readChar());
 223  980 } while (!eof() && Character.isLetter((char) getChar()));
 224  236 Trace.param(this, method, "return", buffer.toString());
 225  236 Trace.end(this, method);
 226  236 return buffer.toString();
 227    }
 228   
 229  3260 private int readPureWhitespace() {
 230  3260 int lines = 0;
 231  3260 while (getChar() != -1 && Character.isWhitespace((char) getChar())) {
 232  1658 if ('\n' == (char) getChar()) {
 233  302 lines++;
 234    }
 235  1658 readChar();
 236    }
 237  3260 return lines;
 238    }
 239   
 240  591 protected final Operator getOperator(final String token) {
 241  591 Operator result = null;
 242  591 if (token == null) {
 243  0 return result;
 244    }
 245  591 for (int i = 0; i < getOperators().size(); i++) {
 246  18400 if (token.equals(((Operator) getOperators().get(i)).getStartSymbol())) {
 247  185 result = (Operator) getOperators().get(i);
 248  185 break;
 249    }
 250    }
 251  591 return result;
 252    }
 253   
 254  552 protected final List getOperators(final String token) {
 255  552 final List result = new ArrayList();
 256  552 if (token == null) {
 257  0 return result;
 258    }
 259  552 for (int i = 0; i < getOperators().size(); i++) {
 260  20928 if (token.equals(((Operator) getOperators().get(i)).getStartSymbol())) {
 261  146 result.add(getOperators().get(i));
 262    }
 263    }
 264  552 return result;
 265    }
 266   
 267  916 protected boolean eot(final String token) {
 268  916 return token == null || token.trim().length() == 0;
 269    }
 270   
 271    }