/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.felix.gogo.runtime; import java.util.regex.Pattern; public class Tokenizer extends BaseTokenizer { private final Pattern redir = Pattern.compile("[0-9&]?>|[0-9]?>>|[0-9]?>&|[0-9]?<|[0-9]?<>|<<<|<<\\-?"); protected boolean inArray; protected int word = 0; protected Token pushed; protected Token last; public Tokenizer(CharSequence text) { super(text); } public Token text() { return text; } public Token next() { if (pushed != null) { Token t = pushed; pushed = null; return t; } skipSpace(last == null || Token.eq(last, "\n")); int start = index - 1; Token t, tn; while (true) { switch (ch) { case EOT: return token(start); case '[': word = 0; inArray = true; return token(start); case ']': inArray = false; word++; return token(start); case '{': if (start == index - 1 && Character.isWhitespace(peek())) { word = 0; return token(start); } else { if (ch == '{') { find('}', '{'); } else { find(')', '('); } getch(); break; } case '(': if (start == index - 1) { word = 0; return token(start); } else { if (ch == '{') { find('}', '{'); } else { find(')', '('); } getch(); break; } case '>': case '<': t = text.subSequence(start, index); if (!eot()) { tn = text.subSequence(start, index + 1); if (redir.matcher(tn).matches()) { getch(); break; } } if (redir.matcher(t).matches() && start < index - 1) { getch(); } word = 0; return token(start); case '-': t = text.subSequence(start, index); if (redir.matcher(t).matches()) { getch(); return token(start); } else { getch(); break; } case '&': // beginning of token if (start == index - 1) { if (peek() == '&' || peek() == '>') { getch(); getch(); } word = 0; return token(start); } // in the middle of a redirection else if (redir.matcher(text.subSequence(start, index)).matches()) { getch(); break; } else { word = 0; return token(start); } case '|': if (start == index - 1 && (peek() == '|' || peek() == '&')) { getch(); getch(); } word = 0; return token(start); case ';': word = 0; return token(start); case '}': case ')': case ' ': case '\t': case '\n': case '\r': word++; return token(start); case '=': if (inArray || word < 1 || index == start + 1) { word++; return token(start); } getch(); break; case '\\': escape(); getch(); break; case '\'': case '"': skipQuote(); getch(); break; default: getch(); break; } } } private Token token(int start) { if (start == index - 1) { if (ch == EOT) { return null; } if (ch == '\r' && peek() == '\n') { getch(); } getch(); last = text.subSequence(index - 2, index - 1); } else { last = text.subSequence(start, index - 1); } return last; } public void push(Token token) { this.pushed = token; } public Token readHereDoc(boolean ignoreLeadingTabs) { final short sLine = line; final short sCol = column; int start; int nlIndex; boolean nl; // Find word skipSpace(); start = index - 1; while (ch != '\n' && ch != EOT) { getch(); } if (ch == EOT) { throw new EOFError(sLine, sCol, "expected here-doc start", "heredoc", "foo\n"); } Token token = text.subSequence(start, index - 1); getch(); start = index - 1; nlIndex = start; nl = true; // Get heredoc while (true) { if (nl) { if (ignoreLeadingTabs && ch == '\t') { nlIndex++; } else { nl = false; } } if (ch == '\n' || ch == EOT) { Token s = text.subSequence(nlIndex, index - 1); if (Token.eq(s, token)) { Token hd = text.subSequence(start, s.start()); getch(); return hd; } nlIndex = index; nl = true; } if (ch == EOT) { throw new EOFError(sLine, sCol, "unexpected eof found in here-doc", "heredoc", "\n" + token.toString() + "\n"); } getch(); } } }