Clover coverage report - Code Coverage for hivemind release 1.1-rc-1
Coverage timestamp: Fri Sep 23 2005 10:46:55 EDT
file stats: LOC: 139   Methods: 4
NCLOC: 73   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Lexer.java 100% 100% 100% 100%
coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.hivemind.conditional;
 16   
 17    import org.apache.hivemind.util.Defense;
 18   
 19    /**
 20    * Parses a string into a series of {@link org.apache.hivemind.conditional.Token}s.
 21    *
 22    * @author Howard M. Lewis Ship
 23    * @since 1.1
 24    */
 25    class Lexer
 26    {
 27    private char[] _input;
 28   
 29    private int _cursor = 0;
 30   
 31    private static final Token OPAREN = new Token(TokenType.OPAREN);
 32   
 33    private static final Token CPAREN = new Token(TokenType.CPAREN);
 34   
 35    private static final Token AND = new Token(TokenType.AND);
 36   
 37    private static final Token OR = new Token(TokenType.OR);
 38   
 39    private static final Token NOT = new Token(TokenType.NOT);
 40   
 41    private static final Token PROPERTY = new Token(TokenType.PROPERTY);
 42   
 43    private static final Token CLASS = new Token(TokenType.CLASS);
 44   
 45  17 Lexer(String input)
 46    {
 47  17 Defense.notNull(input, "input");
 48   
 49  17 _input = input.toCharArray();
 50    }
 51   
 52    /**
 53    * Returns the next token from the input, or null when all tokens have been recognized.
 54    */
 55   
 56  63 Token next()
 57    {
 58  63 while (_cursor < _input.length)
 59    {
 60  79 char ch = _input[_cursor];
 61   
 62  79 if (ch == ')')
 63    {
 64  3 _cursor++;
 65  3 return CPAREN;
 66    }
 67   
 68  76 if (ch == '(')
 69    {
 70  4 _cursor++;
 71  4 return OPAREN;
 72    }
 73   
 74  72 if (Character.isWhitespace(ch))
 75    {
 76  27 _cursor++;
 77  27 continue;
 78    }
 79   
 80  45 if (isSymbolChar(ch))
 81  44 return readSymbol();
 82   
 83  1 throw new RuntimeException(ConditionalMessages.unexpectedCharacter(_cursor, _input));
 84    }
 85   
 86  11 return null;
 87    }
 88   
 89    /**
 90    * This is somewhat limited; a complete regexp would only allow dots within the text, would not
 91    * allow consecutive dots, and would require that the string start with letter or underscore.
 92    */
 93   
 94  282 private boolean isSymbolChar(char ch)
 95    {
 96  282 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')
 97    || (ch == '-') || (ch == '.') || (ch == '_');
 98    }
 99   
 100    /**
 101    * Reads the next symbol at the cursor position, leaving the cursor on the character after the
 102    * symbol. Also recognizes keywords.
 103    */
 104   
 105  44 private Token readSymbol()
 106    {
 107  44 int start = _cursor;
 108   
 109  44 while (true)
 110    {
 111  247 _cursor++;
 112   
 113  247 if (_cursor >= _input.length)
 114  10 break;
 115   
 116  237 if (!isSymbolChar(_input[_cursor]))
 117  34 break;
 118    }
 119   
 120  44 String symbol = new String(_input, start, _cursor - start);
 121   
 122  44 if (symbol.equalsIgnoreCase("and"))
 123  4 return AND;
 124   
 125  40 if (symbol.equalsIgnoreCase("or"))
 126  2 return OR;
 127   
 128  38 if (symbol.equalsIgnoreCase("not"))
 129  6 return NOT;
 130   
 131  32 if (symbol.equalsIgnoreCase("property"))
 132  10 return PROPERTY;
 133   
 134  22 if (symbol.equalsIgnoreCase("class"))
 135  7 return CLASS;
 136   
 137  15 return new Token(TokenType.SYMBOL, symbol);
 138    }
 139    }