[dna-commits] DNA SVN: r1195 - in trunk/dna-common/src: test/java/org/jboss/dna/common/text and 1 other directory.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Wed Sep 9 15:30:42 EDT 2009


Author: rhauch
Date: 2009-09-09 15:30:42 -0400 (Wed, 09 Sep 2009)
New Revision: 1195

Modified:
   trunk/dna-common/src/main/java/org/jboss/dna/common/text/TokenStream.java
   trunk/dna-common/src/test/java/org/jboss/dna/common/text/TokenStreamTest.java
Log:
Added more convenience methods on TokenStream parser framework.

Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/text/TokenStream.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/TokenStream.java	2009-09-04 20:57:55 UTC (rev 1194)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/TokenStream.java	2009-09-09 19:30:42 UTC (rev 1195)
@@ -537,6 +537,40 @@
     }
 
     /**
+     * Attempt to consume this current token as the next tokens as long as they match the expected values, or throw an exception
+     * if the token does not match.
+     * <p>
+     * The {@link #ANY_VALUE ANY_VALUE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param nextTokens the expected values for the next tokens
+     * @throws ParsingException if the current token doesn't match the supplied value
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public void consume( String[] nextTokens ) throws ParsingException, IllegalStateException {
+        for (String nextExpected : nextTokens) {
+            consume(nextExpected);
+        }
+    }
+
+    /**
+     * Attempt to consume this current token as the next tokens as long as they match the expected values, or throw an exception
+     * if the token does not match.
+     * <p>
+     * The {@link #ANY_VALUE ANY_VALUE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param nextTokens the expected values for the next tokens
+     * @throws ParsingException if the current token doesn't match the supplied value
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public void consume( Iterable<String> nextTokens ) throws ParsingException, IllegalStateException {
+        for (String nextExpected : nextTokens) {
+            consume(nextExpected);
+        }
+    }
+
+    /**
      * Attempt to consume this current token if it matches the expected value, and return whether this method was indeed able to
      * consume the token.
      * <p>
@@ -632,6 +666,86 @@
     }
 
     /**
+     * Attempt to consume this current token and the next tokens if and only if they match the expected values, and return whether
+     * this method was indeed able to consume all of the supplied tokens.
+     * <p>
+     * This is <i>not</i> the same as calling {@link #canConsume(String)} for each of the supplied arguments, since this method
+     * ensures that <i>all</i> of the supplied values can be consumed.
+     * </p>
+     * <p>
+     * This method <i>is</i> equivalent to calling the following:
+     * 
+     * <pre>
+     * 
+     * if ( tokens.matches(currentExpected,expectedForNextTokens) ) { tokens.consume(currentExpected,expectedForNextTokens); }
+     * 
+     * </pre>
+     * </p>
+     * <p>
+     * The {@link #ANY_VALUE ANY_VALUE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param nextTokens the expected values of the next tokens
+     * @return true if the current token did match and was consumed, or false if the current token did not match and therefore was
+     *         not consumed
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean canConsume( String[] nextTokens ) throws IllegalStateException {
+        if (completed) return false;
+        ListIterator<Token> iter = tokens.listIterator(tokenIterator.previousIndex());
+        Token token = null;
+        for (String nextExpected : nextTokens) {
+            if (!iter.hasNext()) return false;
+            token = iter.next();
+            if (nextExpected == ANY_VALUE) continue;
+            if (!token.matches(nextExpected)) return false;
+        }
+        this.tokenIterator = iter;
+        this.currentToken = tokenIterator.hasNext() ? tokenIterator.next() : null;
+        return true;
+    }
+
+    /**
+     * Attempt to consume this current token and the next tokens if and only if they match the expected values, and return whether
+     * this method was indeed able to consume all of the supplied tokens.
+     * <p>
+     * This is <i>not</i> the same as calling {@link #canConsume(String)} for each of the supplied arguments, since this method
+     * ensures that <i>all</i> of the supplied values can be consumed.
+     * </p>
+     * <p>
+     * This method <i>is</i> equivalent to calling the following:
+     * 
+     * <pre>
+     * 
+     * if ( tokens.matches(currentExpected,expectedForNextTokens) ) { tokens.consume(currentExpected,expectedForNextTokens); }
+     * 
+     * </pre>
+     * </p>
+     * <p>
+     * The {@link #ANY_VALUE ANY_VALUE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param nextTokens the expected values of the next tokens
+     * @return true if the current token did match and was consumed, or false if the current token did not match and therefore was
+     *         not consumed
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean canConsume( Iterable<String> nextTokens ) throws IllegalStateException {
+        if (completed) return false;
+        ListIterator<Token> iter = tokens.listIterator(tokenIterator.previousIndex());
+        Token token = null;
+        for (String nextExpected : nextTokens) {
+            if (!iter.hasNext()) return false;
+            token = iter.next();
+            if (nextExpected == ANY_VALUE) continue;
+            if (!token.matches(nextExpected)) return false;
+        }
+        this.tokenIterator = iter;
+        this.currentToken = tokenIterator.hasNext() ? tokenIterator.next() : null;
+        return true;
+    }
+
+    /**
      * Determine if the current token matches the expected value.
      * <p>
      * The {@link #ANY_VALUE ANY_VALUE} constant can be used as a wildcard.
@@ -695,6 +809,52 @@
     }
 
     /**
+     * Determine if the next few tokens match the expected values.
+     * <p>
+     * The {@link #ANY_VALUE ANY_VALUE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param nextTokens the expected value of the next tokens
+     * @return true if the tokens did match, or false otherwise
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean matches( String[] nextTokens ) throws IllegalStateException {
+        if (completed) return false;
+        ListIterator<Token> iter = tokens.listIterator(tokenIterator.previousIndex());
+        Token token = null;
+        for (String nextExpected : nextTokens) {
+            if (!iter.hasNext()) return false;
+            token = iter.next();
+            if (nextExpected == ANY_VALUE) continue;
+            if (!token.matches(nextExpected)) return false;
+        }
+        return true;
+    }
+
+    /**
+     * Determine if the next few tokens match the expected values.
+     * <p>
+     * The {@link #ANY_VALUE ANY_VALUE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param nextTokens the expected value of the next tokens
+     * @return true if the tokens did match, or false otherwise
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean matches( Iterable<String> nextTokens ) throws IllegalStateException {
+        if (completed) return false;
+        ListIterator<Token> iter = tokens.listIterator(tokenIterator.previousIndex());
+        Token token = null;
+        for (String nextExpected : nextTokens) {
+            if (!iter.hasNext()) return false;
+            token = iter.next();
+            if (nextExpected == ANY_VALUE) continue;
+            if (!token.matches(nextExpected)) return false;
+        }
+        return true;
+    }
+
+    /**
      * Determine if the next few tokens have the supplied types.
      * <p>
      * The {@link #ANY_TYPE ANY_TYPE} constant can be used in the expected values as a wildcard.
@@ -722,6 +882,29 @@
     }
 
     /**
+     * Determine if the next few tokens have the supplied types.
+     * <p>
+     * The {@link #ANY_TYPE ANY_TYPE} constant can be used in the expected values as a wildcard.
+     * </p>
+     * 
+     * @param typesForNextTokens the expected type for each of the next tokens
+     * @return true if the tokens did match, or false otherwise
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean matches( int[] typesForNextTokens ) throws IllegalStateException {
+        if (completed) return false;
+        ListIterator<Token> iter = tokens.listIterator(tokenIterator.previousIndex());
+        Token token = null;
+        for (int nextExpectedType : typesForNextTokens) {
+            if (!iter.hasNext()) return false;
+            token = iter.next();
+            if (nextExpectedType == ANY_TYPE) continue;
+            if (token.type() != nextExpectedType) return false;
+        }
+        return true;
+    }
+
+    /**
      * Determine if the next token matches one of the supplied values.
      * 
      * @param firstOption the first option for the value of the current token
@@ -741,6 +924,38 @@
     }
 
     /**
+     * Determine if the next token matches one of the supplied values.
+     * 
+     * @param options the options for the value of the current token
+     * @return true if the current token's value did match one of the suplied options, or false otherwise
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean matchesAnyOf( String[] options ) throws IllegalStateException {
+        if (completed) return false;
+        Token current = currentToken();
+        for (String option : options) {
+            if (current.matches(option)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Determine if the next token matches one of the supplied values.
+     * 
+     * @param options the options for the value of the current token
+     * @return true if the current token's value did match one of the suplied options, or false otherwise
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean matchesAnyOf( Iterable<String> options ) throws IllegalStateException {
+        if (completed) return false;
+        Token current = currentToken();
+        for (String option : options) {
+            if (current.matches(option)) return true;
+        }
+        return false;
+    }
+
+    /**
      * Determine if the next token have one of the supplied types.
      * 
      * @param firstTypeOption the first option for the type of the current token
@@ -760,6 +975,22 @@
     }
 
     /**
+     * Determine if the next token have one of the supplied types.
+     * 
+     * @param typeOptions the options for the type of the current token
+     * @return true if the current token's type matched one of the supplied options, or false otherwise
+     * @throws IllegalStateException if this method was called before the stream was {@link #start() started}
+     */
+    public boolean matchesAnyOf( int[] typeOptions ) throws IllegalStateException {
+        if (completed) return false;
+        int currentType = currentToken().type();
+        for (int nextTypeOption : typeOptions) {
+            if (currentType == nextTypeOption) return true;
+        }
+        return false;
+    }
+
+    /**
      * Determine if this stream has another token beyond the current position.
      * 
      * @return true if there is another token, or false otherwise

Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/text/TokenStreamTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/text/TokenStreamTest.java	2009-09-04 20:57:55 UTC (rev 1194)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/text/TokenStreamTest.java	2009-09-09 19:30:42 UTC (rev 1195)
@@ -292,6 +292,14 @@
     }
 
     @Test
+    public void shouldReturnTrueFromCanConsumeArrayOfTokensIfTheyAllMatch() {
+        makeCaseInsensitive();
+        assertThat(tokens.matches(new String[] {"SELECT", "ALL", "COLUMNS", "FROM", "THIS", "TABLE"}), is(true));
+        assertThat(tokens.canConsume(new String[] {"SELECT", "ALL", "COLUMNS", "FROM", "THIS", "TABLE"}), is(true));
+        assertThat(tokens.hasNext(), is(false));
+    }
+
+    @Test
     public void shouldReturnTrueFromCanConsumeMultipleTokensIfTheyDoNotAllMatch() {
         makeCaseInsensitive();
         // Unable to consume unless they all match ...



More information about the dna-commits mailing list