Create Lexer for Expression parser
Factored out VersionParser.CharStream into a separate class and made it generic to use in the Lexer. Did some refactoring of VersionParser.
This commit is contained in:
parent
87bb03dd7f
commit
2dc8bd8930
|
@ -29,11 +29,11 @@ package com.github.zafarkhaja.semver;
|
|||
*/
|
||||
public class ParserException extends RuntimeException {
|
||||
|
||||
ParserException(String message) {
|
||||
public ParserException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
ParserException() {
|
||||
public ParserException() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package com.github.zafarkhaja.semver;
|
||||
|
||||
import com.github.zafarkhaja.semver.VersionParser.CharStream;
|
||||
import com.github.zafarkhaja.semver.util.Stream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import static com.github.zafarkhaja.semver.VersionParser.Char.*;
|
||||
|
@ -34,127 +34,70 @@ import static com.github.zafarkhaja.semver.VersionParser.Char.*;
|
|||
*/
|
||||
class VersionParser implements Parser<Version> {
|
||||
|
||||
static class CharStream {
|
||||
|
||||
static interface CharType {
|
||||
boolean isMatchedBy(char chr);
|
||||
}
|
||||
|
||||
private final char[] data;
|
||||
|
||||
private int offset = 0;
|
||||
|
||||
static final char EOL = (char) -1;
|
||||
|
||||
CharStream(String input) {
|
||||
data = input.toCharArray();
|
||||
}
|
||||
|
||||
char consume() {
|
||||
if (offset + 1 <= data.length) {
|
||||
return data[offset++];
|
||||
}
|
||||
return EOL;
|
||||
}
|
||||
|
||||
char consume(CharType... expected) {
|
||||
char la = lookahead(1);
|
||||
for (CharType charType : expected) {
|
||||
if (charType.isMatchedBy(la)) {
|
||||
return consume();
|
||||
}
|
||||
}
|
||||
throw new UnexpectedCharacterException(la, expected);
|
||||
}
|
||||
|
||||
char lookahead() {
|
||||
return lookahead(1);
|
||||
}
|
||||
|
||||
char lookahead(int pos) {
|
||||
int idx = offset + pos - 1;
|
||||
if (idx < data.length) {
|
||||
return data[idx];
|
||||
}
|
||||
return EOL;
|
||||
}
|
||||
|
||||
boolean positiveLookahead(CharType... expected) {
|
||||
char la = lookahead(1);
|
||||
for (CharType charType : expected) {
|
||||
if (charType.isMatchedBy(la)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean positiveLookaheadBefore(CharType before, CharType... expected) {
|
||||
char la;
|
||||
for (int i = 1; i <= data.length; i++) {
|
||||
la = lookahead(i);
|
||||
if (before.isMatchedBy(la)) {
|
||||
break;
|
||||
}
|
||||
for (CharType charType : expected) {
|
||||
if (charType.isMatchedBy(la)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char[] toArray() {
|
||||
return data.clone();
|
||||
}
|
||||
}
|
||||
|
||||
static enum Char implements CharStream.CharType {
|
||||
static enum Char implements Stream.ElementType<Character> {
|
||||
|
||||
DIGIT {
|
||||
@Override
|
||||
public boolean isMatchedBy(char chr) {
|
||||
public boolean isMatchedBy(Character chr) {
|
||||
if (chr == null) {
|
||||
return false;
|
||||
}
|
||||
return chr >= '0' && chr <= '9';
|
||||
}
|
||||
},
|
||||
LETTER {
|
||||
@Override
|
||||
public boolean isMatchedBy(char chr) {
|
||||
public boolean isMatchedBy(Character chr) {
|
||||
if (chr == null) {
|
||||
return false;
|
||||
}
|
||||
return (chr >= 'a' && chr <= 'z')
|
||||
|| (chr >= 'A' && chr <= 'Z');
|
||||
}
|
||||
},
|
||||
DOT {
|
||||
@Override
|
||||
public boolean isMatchedBy(char chr) {
|
||||
public boolean isMatchedBy(Character chr) {
|
||||
if (chr == null) {
|
||||
return false;
|
||||
}
|
||||
return chr == '.';
|
||||
}
|
||||
},
|
||||
HYPHEN {
|
||||
@Override
|
||||
public boolean isMatchedBy(char chr) {
|
||||
public boolean isMatchedBy(Character chr) {
|
||||
if (chr == null) {
|
||||
return false;
|
||||
}
|
||||
return chr == '-';
|
||||
}
|
||||
},
|
||||
PLUS {
|
||||
@Override
|
||||
public boolean isMatchedBy(char chr) {
|
||||
public boolean isMatchedBy(Character chr) {
|
||||
if (chr == null) {
|
||||
return false;
|
||||
}
|
||||
return chr == '+';
|
||||
}
|
||||
},
|
||||
EOL {
|
||||
@Override
|
||||
public boolean isMatchedBy(char chr) {
|
||||
return chr == CharStream.EOL;
|
||||
public boolean isMatchedBy(Character chr) {
|
||||
return chr == null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final CharStream chars;
|
||||
private final Stream<Character> chars;
|
||||
|
||||
VersionParser(String input) {
|
||||
chars = new CharStream(input);
|
||||
Character[] elements = new Character[input.length()];
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
elements[i] = Character.valueOf(input.charAt(i));
|
||||
}
|
||||
chars = new Stream<Character>(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,8 +241,8 @@ class VersionParser implements Parser<Version> {
|
|||
}
|
||||
|
||||
private void checkForLeadingZeroes() {
|
||||
char la1 = chars.lookahead(1);
|
||||
char la2 = chars.lookahead(2);
|
||||
Character la1 = chars.lookahead(1);
|
||||
Character la2 = chars.lookahead(2);
|
||||
if (la1 == '0' && DIGIT.isMatchedBy(la2)) {
|
||||
throw new GrammarException(
|
||||
"Numeric identifier MUST NOT contain leading zeroes"
|
||||
|
|
145
src/main/java/com/github/zafarkhaja/semver/expr/Lexer.java
Normal file
145
src/main/java/com/github/zafarkhaja/semver/expr/Lexer.java
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.expr;
|
||||
|
||||
import com.github.zafarkhaja.semver.util.Stream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
class Lexer {
|
||||
|
||||
static class Token {
|
||||
|
||||
enum Type implements Stream.ElementType<Token> {
|
||||
|
||||
NUMERIC("0|[1-9][0-9]*"),
|
||||
DOT("\\."),
|
||||
HYPHEN("-"),
|
||||
EQUAL("="),
|
||||
NOT_EQUAL("!="),
|
||||
GREATER(">(?!=)"),
|
||||
GREATER_EQUAL(">="),
|
||||
LESS("<(?!=)"),
|
||||
LESS_EQUAL("<="),
|
||||
TILDE("~"),
|
||||
STAR("\\*"),
|
||||
AND("&"),
|
||||
OR("\\|"),
|
||||
NOT("!(?!=)"),
|
||||
LEFT_PAREN("\\("),
|
||||
RIGHT_PAREN("\\)"),
|
||||
WHITESPACE("\\s+"),
|
||||
EOL("?!") {
|
||||
@Override
|
||||
public boolean isMatchedBy(Token token) {
|
||||
return token == null;
|
||||
}
|
||||
};
|
||||
|
||||
final Pattern pattern;
|
||||
|
||||
private Type(String regexp) {
|
||||
pattern = Pattern.compile("^(" + regexp + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name() + "(" + pattern + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatchedBy(Token token) {
|
||||
if (token == null) {
|
||||
return false;
|
||||
}
|
||||
return this == token.type;
|
||||
}
|
||||
}
|
||||
|
||||
final Type type;
|
||||
final String lexeme;
|
||||
|
||||
Token(Type type, String lexeme) {
|
||||
this.type = type;
|
||||
this.lexeme = (lexeme == null) ? "" : lexeme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof Token)) {
|
||||
return false;
|
||||
}
|
||||
Token token = (Token) other;
|
||||
return type.equals(token.type) && lexeme.equals(token.lexeme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 71 * hash + type.hashCode();
|
||||
hash = 71 * hash + lexeme.hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.name() + "(" + lexeme + ")";
|
||||
}
|
||||
}
|
||||
|
||||
Lexer() {
|
||||
|
||||
}
|
||||
|
||||
Stream<Token> tokenize(String input) {
|
||||
List<Token> tokens = new ArrayList<Token>();
|
||||
while (!input.isEmpty()) {
|
||||
boolean matched = false;
|
||||
for (Token.Type tokenType : Token.Type.values()) {
|
||||
Matcher matcher = tokenType.pattern.matcher(input);
|
||||
if (matcher.find()) {
|
||||
matched = true;
|
||||
input = matcher.replaceFirst("");
|
||||
if (tokenType != Token.Type.WHITESPACE) {
|
||||
tokens.add(new Token(tokenType, matcher.group()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
throw new LexerException(input);
|
||||
}
|
||||
}
|
||||
return new Stream<Token>(tokens.toArray(new Token[tokens.size()]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.expr;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class LexerException extends RuntimeException {
|
||||
|
||||
private final String expr;
|
||||
|
||||
LexerException(String expr) {
|
||||
this.expr = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Illegal character near '" + expr + "'";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.expr;
|
||||
|
||||
import com.github.zafarkhaja.semver.ParserException;
|
||||
import com.github.zafarkhaja.semver.expr.Lexer.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class UnexpectedTokenException extends ParserException {
|
||||
|
||||
private final Token unexpected;
|
||||
private final Token.Type[] expected;
|
||||
|
||||
UnexpectedTokenException(Token token, Token.Type... expected) {
|
||||
unexpected = token;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String message = "Unexpected token '" + unexpected + "'";
|
||||
if (expected.length > 0) {
|
||||
message += ", expecting '" + Arrays.toString(expected) + "'";
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
148
src/main/java/com/github/zafarkhaja/semver/util/Stream.java
Normal file
148
src/main/java/com/github/zafarkhaja/semver/util/Stream.java
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class Stream<E> implements Iterable<E> {
|
||||
|
||||
public static interface ElementType<E> {
|
||||
boolean isMatchedBy(E element);
|
||||
}
|
||||
|
||||
private final E[] elements;
|
||||
|
||||
private int offset = 0;
|
||||
|
||||
public Stream(E[] elements) {
|
||||
this.elements = elements.clone();
|
||||
}
|
||||
|
||||
public E consume() {
|
||||
if (offset >= elements.length) {
|
||||
return null;
|
||||
}
|
||||
return elements[offset++];
|
||||
}
|
||||
|
||||
public E consume(ElementType<E>... expected) {
|
||||
E lookahead = lookahead(1);
|
||||
for (ElementType<E> type : expected) {
|
||||
if (type.isMatchedBy(lookahead)) {
|
||||
return consume();
|
||||
}
|
||||
}
|
||||
throw new UnexpectedElementTypeException(lookahead, expected);
|
||||
}
|
||||
|
||||
public E lookahead() {
|
||||
return lookahead(1);
|
||||
}
|
||||
|
||||
public E lookahead(int position) {
|
||||
int idx = offset + position - 1;
|
||||
if (idx < elements.length) {
|
||||
return elements[idx];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean positiveLookahead(ElementType<E>... expected) {
|
||||
for (ElementType<E> type : expected) {
|
||||
if (type.isMatchedBy(lookahead(1))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean positiveLookaheadBefore(
|
||||
ElementType<E> before,
|
||||
ElementType<E>... expected
|
||||
) {
|
||||
E lookahead;
|
||||
for (int i = 1; i <= elements.length; i++) {
|
||||
lookahead = lookahead(i);
|
||||
if (before.isMatchedBy(lookahead)) {
|
||||
break;
|
||||
}
|
||||
for (ElementType<E> type : expected) {
|
||||
if (type.isMatchedBy(lookahead)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean positiveLookaheadUntil(
|
||||
int until,
|
||||
ElementType<E>... expected
|
||||
) {
|
||||
for (int i = 1; i <= until; i++) {
|
||||
for (ElementType<E> type : expected) {
|
||||
if (type.isMatchedBy(lookahead(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
|
||||
private int index = offset;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < elements.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (index >= elements.length) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return elements[index++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public E[] toArray() {
|
||||
return Arrays.copyOfRange(elements, offset, elements.length);
|
||||
}
|
||||
}
|
|
@ -21,28 +21,28 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver;
|
||||
package com.github.zafarkhaja.semver.util;
|
||||
|
||||
import com.github.zafarkhaja.semver.VersionParser.CharStream.CharType;
|
||||
import com.github.zafarkhaja.semver.util.Stream.ElementType;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class UnexpectedCharacterException extends ParserException {
|
||||
public class UnexpectedElementTypeException extends RuntimeException {
|
||||
|
||||
private final char unexpected;
|
||||
private final CharType[] expected;
|
||||
private final Object unexpected;
|
||||
private final ElementType<?>[] expected;
|
||||
|
||||
UnexpectedCharacterException(char chr, CharType... expected) {
|
||||
unexpected = chr;
|
||||
UnexpectedElementTypeException(Object element, ElementType<?>... expected) {
|
||||
unexpected = element;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String message = "Unexpected character '" + unexpected + "'";
|
||||
String message = "Unexpected element '" + unexpected + "'";
|
||||
if (expected.length > 0) {
|
||||
message += ", expecting '" + Arrays.toString(expected) + "'";
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver;
|
||||
|
||||
import com.github.zafarkhaja.semver.VersionParser.Char;
|
||||
import com.github.zafarkhaja.semver.VersionParser.CharStream;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class VersionParserCharStreamTest {
|
||||
|
||||
@Test
|
||||
public void shouldBeBackedByCharArray() {
|
||||
String input = "abc";
|
||||
CharStream chars = new CharStream(input);
|
||||
assertArrayEquals(input.toCharArray(), chars.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotReturnRealCharArray() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
char[] charArray = chars.toArray();
|
||||
charArray[0] = 'z';
|
||||
assertEquals('z', charArray[0]);
|
||||
assertEquals('a', chars.lookahead());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldConsumeCharactersOneByOne() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
assertEquals('a', chars.consume());
|
||||
assertEquals('b', chars.consume());
|
||||
assertEquals('c', chars.consume());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEolWhenNothingLeftToConsume() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
assertEquals('a', chars.consume());
|
||||
assertEquals('b', chars.consume());
|
||||
assertEquals('c', chars.consume());
|
||||
assertEquals(CharStream.EOL, chars.consume());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRaiseErrorWhenUnexpectedCharTypeConsumed() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
try {
|
||||
chars.consume(Char.DIGIT);
|
||||
} catch (UnexpectedCharacterException e) {
|
||||
return;
|
||||
}
|
||||
fail("Should raise error when unexpected character type is consumed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLookaheadWithoutConsuming() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
assertEquals('a', chars.lookahead());
|
||||
assertEquals('a', chars.lookahead());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLookaheadArbitraryNumberOfCharacters() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
assertEquals('a', chars.lookahead(1));
|
||||
assertEquals('b', chars.lookahead(2));
|
||||
assertEquals('c', chars.lookahead(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEolWhenNothingLeftToLookahead() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
assertEquals('a', chars.consume());
|
||||
assertEquals('b', chars.consume());
|
||||
assertEquals('c', chars.consume());
|
||||
assertEquals(CharStream.EOL, chars.lookahead());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckIfLookaheadIsOfExpectedTypes() {
|
||||
CharStream chars = new CharStream("abc");
|
||||
assertTrue(chars.positiveLookahead(Char.LETTER));
|
||||
assertFalse(chars.positiveLookahead(Char.DIGIT, Char.PLUS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckIfCharOfExpectedTypesExistBeforeGivenType() {
|
||||
CharStream chars = new CharStream("1.0.0");
|
||||
assertTrue(chars.positiveLookaheadBefore(Char.EOL, Char.DOT));
|
||||
assertFalse(chars.positiveLookaheadBefore(Char.EOL, Char.LETTER));
|
||||
}
|
||||
}
|
|
@ -23,9 +23,8 @@
|
|||
*/
|
||||
package com.github.zafarkhaja.semver;
|
||||
|
||||
import com.github.zafarkhaja.semver.VersionParser.Char;
|
||||
import com.github.zafarkhaja.semver.VersionParser.CharStream;
|
||||
import org.junit.Test;
|
||||
import static com.github.zafarkhaja.semver.VersionParser.Char.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
|
@ -36,49 +35,49 @@ public class VersionParserCharTest {
|
|||
|
||||
@Test
|
||||
public void shouldBeMatchedByDigit() {
|
||||
assertTrue(Char.DIGIT.isMatchedBy('0'));
|
||||
assertTrue(Char.DIGIT.isMatchedBy('9'));
|
||||
assertFalse(Char.DIGIT.isMatchedBy('a'));
|
||||
assertFalse(Char.DIGIT.isMatchedBy('A'));
|
||||
assertTrue(DIGIT.isMatchedBy('0'));
|
||||
assertTrue(DIGIT.isMatchedBy('9'));
|
||||
assertFalse(DIGIT.isMatchedBy('a'));
|
||||
assertFalse(DIGIT.isMatchedBy('A'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeMatchedByLetter() {
|
||||
assertTrue(Char.LETTER.isMatchedBy('a'));
|
||||
assertTrue(Char.LETTER.isMatchedBy('A'));
|
||||
assertFalse(Char.LETTER.isMatchedBy('0'));
|
||||
assertFalse(Char.LETTER.isMatchedBy('9'));
|
||||
assertTrue(LETTER.isMatchedBy('a'));
|
||||
assertTrue(LETTER.isMatchedBy('A'));
|
||||
assertFalse(LETTER.isMatchedBy('0'));
|
||||
assertFalse(LETTER.isMatchedBy('9'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeMatchedByDot() {
|
||||
assertTrue(Char.DOT.isMatchedBy('.'));
|
||||
assertFalse(Char.DOT.isMatchedBy('-'));
|
||||
assertFalse(Char.DOT.isMatchedBy('0'));
|
||||
assertFalse(Char.DOT.isMatchedBy('9'));
|
||||
assertTrue(DOT.isMatchedBy('.'));
|
||||
assertFalse(DOT.isMatchedBy('-'));
|
||||
assertFalse(DOT.isMatchedBy('0'));
|
||||
assertFalse(DOT.isMatchedBy('9'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeMatchedByHyphen() {
|
||||
assertTrue(Char.HYPHEN.isMatchedBy('-'));
|
||||
assertFalse(Char.HYPHEN.isMatchedBy('+'));
|
||||
assertFalse(Char.HYPHEN.isMatchedBy('a'));
|
||||
assertFalse(Char.HYPHEN.isMatchedBy('0'));
|
||||
assertTrue(HYPHEN.isMatchedBy('-'));
|
||||
assertFalse(HYPHEN.isMatchedBy('+'));
|
||||
assertFalse(HYPHEN.isMatchedBy('a'));
|
||||
assertFalse(HYPHEN.isMatchedBy('0'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeMatchedByPlus() {
|
||||
assertTrue(Char.PLUS.isMatchedBy('+'));
|
||||
assertFalse(Char.PLUS.isMatchedBy('-'));
|
||||
assertFalse(Char.PLUS.isMatchedBy('a'));
|
||||
assertFalse(Char.PLUS.isMatchedBy('0'));
|
||||
assertTrue(PLUS.isMatchedBy('+'));
|
||||
assertFalse(PLUS.isMatchedBy('-'));
|
||||
assertFalse(PLUS.isMatchedBy('a'));
|
||||
assertFalse(PLUS.isMatchedBy('0'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeMatchedByEol() {
|
||||
assertTrue(Char.EOL.isMatchedBy(CharStream.EOL));
|
||||
assertFalse(Char.EOL.isMatchedBy('-'));
|
||||
assertFalse(Char.EOL.isMatchedBy('a'));
|
||||
assertFalse(Char.EOL.isMatchedBy('0'));
|
||||
assertTrue(EOL.isMatchedBy(null));
|
||||
assertFalse(EOL.isMatchedBy('-'));
|
||||
assertFalse(EOL.isMatchedBy('a'));
|
||||
assertFalse(EOL.isMatchedBy('0'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.expr;
|
||||
|
||||
import com.github.zafarkhaja.semver.expr.Lexer.*;
|
||||
import com.github.zafarkhaja.semver.util.Stream;
|
||||
import org.junit.Test;
|
||||
import static com.github.zafarkhaja.semver.expr.Lexer.Token.Type.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class LexerTest {
|
||||
|
||||
@Test
|
||||
public void shouldTokenizeVersionString() {
|
||||
Token[] expected = {
|
||||
new Token(GREATER, ">"),
|
||||
new Token(NUMERIC, "1"),
|
||||
new Token(DOT, "."),
|
||||
new Token(NUMERIC, "0"),
|
||||
new Token(DOT, "."),
|
||||
new Token(NUMERIC, "0"),
|
||||
};
|
||||
Lexer lexer = new Lexer();
|
||||
Stream<Token> stream = lexer.tokenize(">1.0.0");
|
||||
assertArrayEquals(expected, stream.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSkipWhitespaces() {
|
||||
Token[] expected = {
|
||||
new Token(GREATER, ">"),
|
||||
new Token(NUMERIC, "1"),
|
||||
};
|
||||
Lexer lexer = new Lexer();
|
||||
Stream<Token> stream = lexer.tokenize("> 1");
|
||||
assertArrayEquals(expected, stream.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRaiseErrorOnIllegalCharacter() {
|
||||
Lexer lexer = new Lexer();
|
||||
try {
|
||||
lexer.tokenize("@1.0.0");
|
||||
} catch (LexerException e) {
|
||||
return;
|
||||
}
|
||||
fail("Should raise error on illegal character");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.expr;
|
||||
|
||||
import com.github.zafarkhaja.semver.expr.Lexer.Token;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.runners.Enclosed;
|
||||
import org.junit.runner.RunWith;
|
||||
import static com.github.zafarkhaja.semver.expr.Lexer.Token.Type.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
@RunWith(Enclosed.class)
|
||||
public class LexerTokenTest {
|
||||
|
||||
public static class EqualsMethodTest {
|
||||
|
||||
@Test
|
||||
public void shouldBeReflexive() {
|
||||
Token token = new Token(NUMERIC, "1");
|
||||
assertTrue(token.equals(token));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeSymmetric() {
|
||||
Token t1 = new Token(EQUAL, "=");
|
||||
Token t2 = new Token(EQUAL, "=");
|
||||
assertTrue(t1.equals(t2));
|
||||
assertTrue(t2.equals(t1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeTransitive() {
|
||||
Token t1 = new Token(GREATER, ">");
|
||||
Token t2 = new Token(GREATER, ">");
|
||||
Token t3 = new Token(GREATER, ">");
|
||||
assertTrue(t1.equals(t2));
|
||||
assertTrue(t2.equals(t3));
|
||||
assertTrue(t1.equals(t3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeConsistent() {
|
||||
Token t1 = new Token(HYPHEN, "-");
|
||||
Token t2 = new Token(HYPHEN, "-");
|
||||
assertTrue(t1.equals(t2));
|
||||
assertTrue(t1.equals(t2));
|
||||
assertTrue(t1.equals(t2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseIfOtherVersionIsOfDifferentType() {
|
||||
Token t1 = new Token(DOT, ".");
|
||||
assertFalse(t1.equals(new String(".")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseIfOtherVersionIsNull() {
|
||||
Token t1 = new Token(AND, "&");
|
||||
Token t2 = null;
|
||||
assertFalse(t1.equals(t2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseIfTypesAreDifferent() {
|
||||
Token t1 = new Token(EQUAL, "=");
|
||||
Token t2 = new Token(NOT_EQUAL, "!=");
|
||||
assertFalse(t1.equals(t2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseIfLexemesAreDifferent() {
|
||||
Token t1 = new Token(NUMERIC, "1");
|
||||
Token t2 = new Token(NUMERIC, "2");
|
||||
assertFalse(t1.equals(t2));
|
||||
}
|
||||
}
|
||||
|
||||
public static class HashCodeMethodTest {
|
||||
|
||||
@Test
|
||||
public void shouldReturnSameHashCodeIfTokensAreEqual() {
|
||||
Token t1 = new Token(NUMERIC, "1");
|
||||
Token t2 = new Token(NUMERIC, "1");
|
||||
assertTrue(t1.equals(t2));
|
||||
assertEquals(t1.hashCode(), t2.hashCode());
|
||||
}
|
||||
}
|
||||
}
|
206
src/test/java/com/github/zafarkhaja/semver/util/StreamTest.java
Normal file
206
src/test/java/com/github/zafarkhaja/semver/util/StreamTest.java
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2013 Zafar Khaja <zafarkhaja@gmail.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.github.zafarkhaja.semver.util;
|
||||
|
||||
import com.github.zafarkhaja.semver.util.Stream.ElementType;
|
||||
import java.util.Iterator;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
||||
*/
|
||||
public class StreamTest {
|
||||
|
||||
@Test
|
||||
public void shouldBeBackedByArray() {
|
||||
Character[] input = {'a', 'b', 'c'};
|
||||
Stream<Character> stream = new Stream<Character>(input);
|
||||
assertArrayEquals(input, stream.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldImplementIterable() {
|
||||
Character[] input = {'a', 'b', 'c'};
|
||||
Stream<Character> stream = new Stream<Character>(input);
|
||||
Iterator<Character> it = stream.iterator();
|
||||
for (Character chr : input) {
|
||||
assertEquals(chr, it.next());
|
||||
}
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotReturnRealElementsArray() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
Character[] charArray = stream.toArray();
|
||||
charArray[0] = Character.valueOf('z');
|
||||
assertEquals(Character.valueOf('z'), charArray[0]);
|
||||
assertEquals(Character.valueOf('a'), stream.toArray()[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnArrayOfElementsThatAreLeftInStream() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
stream.consume();
|
||||
stream.consume();
|
||||
assertEquals(1, stream.toArray().length);
|
||||
assertEquals(Character.valueOf('c'), stream.toArray()[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldConsumeElementsOneByOne() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
assertEquals(Character.valueOf('a'), stream.consume());
|
||||
assertEquals(Character.valueOf('b'), stream.consume());
|
||||
assertEquals(Character.valueOf('c'), stream.consume());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRaiseErrorWhenUnexpectedElementTypeConsumed() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
try {
|
||||
stream.consume(new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} catch (UnexpectedElementTypeException e) {
|
||||
return;
|
||||
}
|
||||
fail("Should raise error when unexpected element type is consumed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLookaheadWithoutConsuming() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
assertEquals(Character.valueOf('a'), stream.lookahead());
|
||||
assertEquals(Character.valueOf('a'), stream.lookahead());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLookaheadArbitraryNumberOfElements() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
assertEquals(Character.valueOf('a'), stream.lookahead(1));
|
||||
assertEquals(Character.valueOf('b'), stream.lookahead(2));
|
||||
assertEquals(Character.valueOf('c'), stream.lookahead(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckIfLookaheadIsOfExpectedTypes() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'a', 'b', 'c'}
|
||||
);
|
||||
assertTrue(stream.positiveLookahead(
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == 'a';
|
||||
}
|
||||
}
|
||||
));
|
||||
assertFalse(stream.positiveLookahead(
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == 'c';
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckIfElementOfExpectedTypesExistBeforeGivenType() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'1', '.', '0', '.', '0'}
|
||||
);
|
||||
assertTrue(stream.positiveLookaheadBefore(
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == '.';
|
||||
}
|
||||
},
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == '1';
|
||||
}
|
||||
}
|
||||
));
|
||||
assertFalse(stream.positiveLookaheadBefore(
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == '1';
|
||||
}
|
||||
},
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == '.';
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckIfElementOfExpectedTypesExistUntilGivenPosition() {
|
||||
Stream<Character> stream = new Stream<Character>(
|
||||
new Character[] {'1', '.', '0', '.', '0'}
|
||||
);
|
||||
assertTrue(stream.positiveLookaheadUntil(
|
||||
3,
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == '0';
|
||||
}
|
||||
}
|
||||
));
|
||||
assertFalse(stream.positiveLookaheadUntil(
|
||||
3,
|
||||
new ElementType<Character>() {
|
||||
@Override
|
||||
public boolean isMatchedBy(Character element) {
|
||||
return element == 'a';
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user