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    
020    package org.crsh.cli.impl.tokenizer;
021    
022    import org.crsh.cli.impl.Delimiter;
023    
024    public class TokenizerImpl extends Tokenizer {
025    
026      /** . */
027      private final CharSequence s;
028    
029      /** . */
030      private int index;
031    
032      /** . */
033      private Delimiter delimiter;
034    
035      public TokenizerImpl(CharSequence s) {
036        this.s = s;
037        this.index = 0;
038        this.delimiter = null;
039      }
040    
041      protected Token parse() {
042        Token token = null;
043        if (index < s.length()) {
044          char c = s.charAt(index);
045          int from = index;
046          while (true) {
047            if (Character.isWhitespace(c)) {
048              index++;
049              if (index < s.length()) {
050                c = s.charAt(index);
051              } else {
052                break;
053              }
054            } else {
055              break;
056            }
057          }
058          if (index > from) {
059            token = new Token.Whitespace(from, s.subSequence(from, index).toString());
060          } else {
061            State state = new State();
062            while (true) {
063              if (Character.isWhitespace(c) && state.escape == Escape.NONE) {
064                break;
065              } else {
066                index++;
067                state.push(c);
068                if (index < s.length()) {
069                  c = s.charAt(index);
070                } else {
071                  break;
072                }
073              }
074            }
075            if (index > from) {
076              switch (state.status) {
077                case INIT: {
078                  token = new Token.Literal.Word(from, s.subSequence(from, index).toString(), state.buffer.toString());
079                  break;
080                }
081                case WORD: {
082                  token = new Token.Literal.Word(from, s.subSequence(from, index).toString(), state.buffer.toString());
083                  break;
084                }
085                case SHORT_OPTION: {
086                  token = new Token.Literal.Option.Short(from, s.subSequence(from, index).toString(), state.buffer.toString());
087                  break;
088                }
089                case LONG_OPTION: {
090                  token = new Token.Literal.Option.Long(from, s.subSequence(from, index).toString(), state.buffer.toString());
091                  break;
092                }
093                default:
094                  throw new AssertionError(state.status);
095              }
096              delimiter = state.escape.delimiter;
097              return token;
098            }
099          }
100        }
101        return token;
102      }
103    
104      public Delimiter getDelimiter() {
105        return delimiter;
106      }
107    }