001/*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020package org.crsh.cli.impl.tokenizer;
021
022import org.crsh.cli.impl.Delimiter;
023
024import java.util.ArrayList;
025import java.util.Iterator;
026import java.util.NoSuchElementException;
027
028public abstract class Tokenizer implements Iterator<Token> {
029
030  /** . */
031  private ArrayList<Token> stack;
032
033  /** . */
034  private int ptr;
035
036  /** . */
037  private int index = 0;
038
039  protected Tokenizer() {
040    this.stack = new ArrayList<Token>();
041    this.ptr = 0;
042  }
043
044  public final boolean hasNext() {
045    if (ptr < stack.size()) {
046      return true;
047    } else {
048      Token next = parse();
049      if (next != null) {
050        stack.add(next);
051      }
052      return next != null;
053    }
054  }
055
056  public final void pushBack(int count) {
057    if (count < 0) {
058      throw new IllegalArgumentException();
059    }
060    if (ptr - count < 0) {
061      throw new IllegalStateException("Trying to push back too many tokens");
062    } else {
063      while (count > 0) {
064        index -= stack.get(--ptr).raw.length();
065        count--;
066      }
067    }
068  }
069
070  public final Token peek() {
071    if (hasNext()) {
072      return stack.get(ptr);
073    } else {
074      return null;
075    }
076  }
077
078  public final Token next() {
079    if (hasNext()) {
080      Token token = stack.get(ptr++);
081      index += token.raw.length();
082      return token;
083    } else {
084      throw new NoSuchElementException();
085    }
086  }
087
088  public final void remove() {
089    throw new UnsupportedOperationException();
090  }
091
092  public final void pushBack() {
093    pushBack(1);
094  }
095
096  protected abstract Token parse();
097
098  public final int getIndex() {
099    return index;
100  }
101
102  public abstract Delimiter getDelimiter();
103}