Przeglądaj źródła

change: Wildard accepts CharSequence
change: SimpleStreamer: detect EOS
new: SimpleStreamer: support for offset & regex
new: CharPredicate: #of char,chars,string,regex

Ranides Atterwim 6 lat temu
rodzic
commit
6d11a36a13

+ 4 - 3
assira.junit/src/main/java/net/ranides/assira/junit/LogObserver.java

@@ -68,12 +68,13 @@ public final class LogObserver {
         return stream().anyMatch(filter);
     }
     
-    public static Stream<LogMessage> forText(Predicate<String> filter) {
+    public static Stream<LogMessage> forText(Predicate<CharSequence> filter) {
         return stream().filter(m -> filter.test(m.text()));
     }
     
-    public static Stream<LogMessage> forText(String text) {
-        return stream().filter(m -> text.equals(m.text()));
+    public static Stream<LogMessage> forText(CharSequence text) {
+        String str = String.valueOf(text);
+        return stream().filter(m -> str.equals(m.text()));
     }
     
     public static Stream<LogMessage> forLevel(IntPredicate filter) {

+ 47 - 1
assira/src/main/java/net/ranides/assira/functional/CharPredicate.java

@@ -6,7 +6,11 @@
  */
 package net.ranides.assira.functional;
 
+import net.ranides.assira.text.StringUtils;
+
+import java.util.Arrays;
 import java.util.function.Predicate;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -22,5 +26,47 @@ public interface CharPredicate extends Predicate<Character> {
     default boolean test(Character c) {
         return c!=null && test(c.charValue());
     }
-    
+
+    @Override
+    default CharPredicate and(Predicate<? super Character> other) {
+        return c -> test(c) && other.test(c);
+    }
+
+    default CharPredicate and(CharPredicate other) {
+        return c -> test(c) && other.test(c);
+    }
+
+    @Override
+    default CharPredicate negate() {
+        return c -> !test(c);
+    }
+
+    @Override
+    default Predicate<Character> or(Predicate<? super Character> other) {
+        return c -> test(c) || other.test(c);
+    }
+
+    default Predicate<Character> or(CharPredicate other) {
+        return c -> test(c) || other.test(c);
+    }
+
+    static CharPredicate of(char ch) {
+        return c -> c == ch;
+    }
+
+    static CharPredicate of(char... chars) {
+        char[] sorted = chars.clone();
+        Arrays.sort(sorted);
+        return c -> Arrays.binarySearch(sorted, c) >= 0;
+    }
+
+    static CharPredicate of(String text) {
+        return of(text.toCharArray());
+    }
+
+    static CharPredicate of(Pattern pattern) {
+        return c -> pattern.matcher(StringUtils.wrap(new char[]{c})).matches();
+
+    }
+
 }

+ 72 - 4
assira/src/main/java/net/ranides/assira/lexer/SimpleStreamer.java

@@ -1,10 +1,14 @@
 package net.ranides.assira.lexer;
 
 import net.ranides.assira.functional.CharPredicate;
+import net.ranides.assira.text.StringUtils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class SimpleStreamer {
 
-    private final char content[];
+    private final char[] content;
 
     private int position;
 
@@ -14,14 +18,16 @@ public class SimpleStreamer {
     }
 
     public boolean end() {
-        return content.length == position;
+        return position >= content.length;
     }
 
     public char peek() {
+        check();
         return content[position];
     }
 
     public String peek(CharPredicate pred) {
+        check();
         int begin = position;
         int current = position;
         while (content.length != current && pred.test(content[current])) {
@@ -30,17 +36,51 @@ public class SimpleStreamer {
         return new String(content, begin, current - begin);
     }
 
+    public String peek(int n) {
+        check(n);
+        return new String(content, position, n);
+    }
+
+    public String peek(Pattern regex) {
+        check();
+        Matcher matcher = matcher(regex);
+        if(!matcher.find()) {
+            return "";
+        } else {
+            return matcher.group();
+        }
+    }
+
     public void skip() {
+        check();
         position++;
     }
 
-    public void skip(CharPredicate pred) {
+    public void skip(int n) {
+        check(n);
+        position += n;
+    }
+
+    public int skip(CharPredicate pred) {
+        int c = position;
         while (!end() && pred.test(peek())) {
-            next();
+            position++;
+        }
+        return position - c;
+    }
+
+    public int skip(Pattern regex) {
+        Matcher matcher = matcher(regex);
+        if(!matcher.find()) {
+            return 0;
+        } else {
+            position += matcher.end();
+            return matcher.end();
         }
     }
 
     public char next() {
+        check();
         return content[position++];
     }
 
@@ -50,4 +90,32 @@ public class SimpleStreamer {
         return new String(content, begin, position - begin);
     }
 
+    public String next(int n) {
+        check(n);
+        position += n;
+        return new String(content, position-n, n);
+    }
+
+    public String next(Pattern regex) {
+        int begin = position;
+        skip(regex);
+        return new String(content, begin, position - begin);
+    }
+
+    private Matcher matcher(Pattern regex) {
+        return regex.matcher(StringUtils.wrap(content, position, content.length));
+    }
+
+    private void check() {
+        if(position >= content.length) {
+            throw new IllegalStateException("Steamer: EOS");
+        }
+    }
+
+    private void check(int n) {
+        if(position+n > content.length) {
+            throw new IllegalStateException("Steamer: EOS (remained " + (content.length - position) + " instead of " + n +")");
+        }
+    }
+
 }

+ 2 - 2
assira/src/main/java/net/ranides/assira/text/Wildcard.java

@@ -14,7 +14,7 @@ import java.util.regex.Pattern;
  *
  * @author Ranides Atterwim <ranides@gmail.com>
  */
-public final class Wildcard implements Serializable, Predicate<String> {
+public final class Wildcard implements Serializable, Predicate<CharSequence> {
 	
 	private static final long serialVersionUID = 2L;	
 	
@@ -40,7 +40,7 @@ public final class Wildcard implements Serializable, Predicate<String> {
     }
 
 	@Override // NOPMD
-	public boolean test(String text) {
+	public boolean test(CharSequence text) {
 		return re.matcher(text).matches();
 	}
 	

+ 37 - 1
assira/src/test/java/net/ranides/assira/lexer/SimpleStreamerTest.java

@@ -2,10 +2,46 @@ package net.ranides.assira.lexer;
 
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import java.util.regex.Pattern;
+
+import static net.ranides.assira.junit.NewAssert.assertThrows;
+import static org.junit.Assert.assertEquals;
 
 public class SimpleStreamerTest {
 
+    @Test
+    public void predicates() {
+        SimpleStreamer streamer = new SimpleStreamer("hello world");
+        streamer.skip(4);
+
+        assertThrows(IllegalStateException.class, () -> {
+            streamer.skip(9);
+        });
+
+        streamer.skip(7);
+
+        assertThrows(IllegalStateException.class, () -> {
+            streamer.skip();
+        });
+    }
+
+    @Test
+    public void patterns() {
+        SimpleStreamer streamer = new SimpleStreamer("hello 1990 world");
+
+        assertEquals("hello", streamer.peek(Pattern.compile("[a-z]+")));
+        assertEquals("hello ", streamer.peek(Pattern.compile("[a-z ]+")));
+        assertEquals("hello 1990", streamer.peek(Pattern.compile("[a-z]+ [0-9]+")));
+
+        assertEquals("hello", streamer.next(Pattern.compile("[a-z]+")));
+        assertEquals(" ", streamer.next(Pattern.compile(" +")));
+        assertEquals("1990", streamer.next(Pattern.compile("[0-9]+")));
+
+        assertEquals(1, streamer.skip(Pattern.compile(" +")));
+        assertEquals("world", streamer.peek(Pattern.compile("[^0-9]+")));
+        assertEquals("world", streamer.next(Pattern.compile("[^0-9]+")));
+    }
+
 
     @Test
     public void usage() {