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.shell.impl.command;
021    
022    import org.crsh.command.ScriptException;
023    
024    class Tokenizer {
025    
026      /** . */
027      private final CharSequence s;
028    
029      /** . */
030      private int index;
031    
032      /** . */
033      private Character c;
034    
035      /**
036       * Create a new tokenizer.
037       *
038       * @param s the sequence to tokenize
039       * @throws NullPointerException if the sequence is null
040       */
041      public Tokenizer(CharSequence s) throws NullPointerException {
042        if (s == null) {
043          throw new NullPointerException();
044        }
045        this.s = s;
046        this.index = 0;
047    
048        // Initialize state
049        // index points to next char to read
050        // c = s.charAt(index - 1);
051        this.c = index < s.length() ? s.charAt(index++) : null;
052      }
053    
054      private void next() {
055        if (index < s.length()) {
056          c = s.charAt(index++);
057        } else {
058          c = null;
059        }
060      }
061    
062      public Token nextToken() {
063        if (c == null) {
064          return Token.EOF;
065        } else {
066          switch (c) {
067            case '|':
068              next();
069              return Token.PIPE;
070            default:
071              return parseCommand();
072          }
073        }
074      }
075    
076      private Token parseCommand() throws ScriptException {
077    
078        //
079        StringBuilder line = new StringBuilder();
080    
081        //
082        Character lastQuote = null;
083        while (c != null) {
084          if (lastQuote == null && (c == '+' || c == '|')) {
085            break;
086          } else {
087            line.append(c);
088            switch (c) {
089              case '"':
090              case '\'':
091                if (lastQuote == null) {
092                  lastQuote = c;
093                } else if (lastQuote != c) {
094                } else {
095                  lastQuote = null;
096                }
097                break;
098              default:
099                break;
100            }
101          }
102    
103          //
104          next();
105        }
106    
107        //
108        return new Token.Command(line.toString());
109      }
110    }