All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.methylene.args.Tokenizer Maven / Gradle / Ivy

The newest version!
package com.github.methylene.args;

import java.util.Iterator;
import java.util.Queue;

public final class Tokenizer {

  // binds the next token if it exists and  is not special
  private final Predicate weakBinding;

  // binds the next token if it exists
  private final Predicate strongBinding;

  // never binds the next token
  private final Predicate atomic;

  // usually "--"
  private final String restDelimiter;

  private Tokenizer(Predicate weakBinding, Predicate strongBinding, Predicate atomic,
                    String restDelimiter) {
    this.weakBinding = weakBinding;
    this.strongBinding = strongBinding;
    this.atomic = atomic;
    this.restDelimiter = restDelimiter;
  }

  /**
   * Create a new tokenizer that uses the provided predicates.
   * @param weakBinding the weak binding predicate
   * @param strongBinding the strong binding predicate
   * @param atomic the atomic predicate
   * @param restDelimiter the rest delimiter
   * @return a tokenizer
   */
  public static Tokenizer create(Predicate weakBinding, Predicate strongBinding,
                                 Predicate atomic, String restDelimiter) {
    return new Tokenizer(weakBinding, strongBinding, atomic, restDelimiter);
  }

  private SimpleToken read(String first, Queue rest) {

    if (rest.isEmpty())
      return SimpleToken.create(first);

    if (atomic.matches(first))
      return SimpleToken.create(first);

    if (strongBinding.matches(first))
      return SimpleToken.create(first, rest.poll().getArg());

    if (weakBinding.matches(first)
        && !weakBinding.matches(rest.peek().getArg())
        && !strongBinding.matches(rest.peek().getArg())
        && !atomic.matches(rest.peek().getArg()))
      return SimpleToken.create(first, rest.poll().getArg());

    return SimpleToken.create(first);

  }

  /**
   * Read the arguments into a list of tokens.
   * @param args a string array
   * @return an iterable
   */
  public Iterable tokenize(final String[] args) {
    return tokenize(Util.toQueue(args));
  }

  private Iterable tokenize(final Queue queue) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {

          private boolean started = false;
          private boolean restMode = false;
          private Token nextToken = null;

          private Token next_(RawArgument nextArg) {
            SimpleToken next;
            if (nextArg == null) {
              next = null;
            } else if (restMode) {
              next = SimpleToken.create("--", nextArg.getArg());
            } else if (restDelimiter != null && restDelimiter.equals(nextArg.getArg())) {
              nextArg = queue.isEmpty() ? null : queue.poll();
              next = nextArg == null ? null : SimpleToken.create(restDelimiter, nextArg.getArg());
              restMode = true;
            } else {
              next = read(nextArg.getArg(), queue);
            }
            return nextArg == null ? null : Token.create(next, nextArg);
          }

          @Override
          public boolean hasNext() {
            if (!started) {
              started = true;
              nextToken = next_(queue.isEmpty() ? null : queue.poll());
            }
            return nextToken != null;
          }

          @Override
          public Token next() {
            Token tmp = nextToken;
            nextToken = next_(queue.isEmpty() ? null : queue.poll());
            return tmp;
          }

          @Override public void remove() {
            throw new UnsupportedOperationException();
          }

        };
      }
    };
  }

  /**
   * Get the weak binding predicate of this instance.
   * An argument that matches this predicate will bind
   * the following one if it exists and is not either weakly binding, strongly binding,
   * atomic or a rest delimiter.
   * @return the weak binding predicate
   */
  public Predicate getWeakBinding() {
    return weakBinding;
  }

  /**
   * Get the strong binding predicate of this instance.
   * An argument that matches this predicate will bind
   * the following one if it exists.
   * This will typically include any explicitly declared parameters.
   * @return the strong binding predicate
   */
  public Predicate getStrongBinding() {
    return strongBinding;
  }

  /**
   * Get the atomic predicate of this instance.
   * An argument that matches this predicate will never bind the following token.
   * If it is not itself bound by a strong binding token or the rest delimiter,
   * it will be read as a flag.
   * @return the atomic predicate
   */
  public Predicate getAtomic() {
    return atomic;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy