/******************************************************************************* * Copyright (c) 2008, 2017 xored software, Inc. and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * xored software, Inc. - initial API and Implementation (Andrei Sobolev) *******************************************************************************/ package org.eclipse.dltk.tcl.internal.parser.raw; public class VariableSubstitution extends TclElement implements ISubstitution { public static final int VAR_SIMPLE = 0; public static final int VAR_ARRAY = 1; public static final int VAR_NAME = 2; private String name; private TclWord index; private int kind; public VariableSubstitution() { } public TclWord getIndex() { return index; } public String getName() { return name; } public static boolean iAm(ICodeScanner scanner) { int c = scanner.read(); if (c == ICodeScanner.EOF) return false; if (c != '$') { scanner.unread(); return false; } int c2 = scanner.read(); scanner.unread(); if (c2 != ICodeScanner.EOF) scanner.unread(); if (!TclTextUtils.isIdentifier(c2) && c2 != '(' && c2 != '{') { return false; } return true; } @Override public boolean readMe(ICodeScanner input, SimpleTclParser parser) throws TclParseException { if (!iAm(input)) return false; setStart(input.getPosition()); this.name = ""; this.kind = VAR_SIMPLE; input.read(); int c = input.read(); if (c == '{') { this.kind = VAR_NAME; while (true) { c = input.read(); if (c == ICodeScanner.EOF) { boolean cont = parser.handleError(new ErrorDescription( Messages.VariableSubstitution_BracesVariableName, getStart(), input.getPosition(), ErrorDescription.ERROR)); if (!cont) { throw new TclParseException( Messages.VariableSubstitution_BracesVariableName, input.getPosition()); } else { break; } } if (c == '}') break; this.name += (char) c; } } else { do { if (c == ICodeScanner.EOF) { break; // stop! } if (TclTextUtils.isIdentifier(c)) { this.name += (char) c; c = input.read(); } else { if (c == '(') { // read index part this.kind = VAR_ARRAY; TclWord cvb = new TclWord(); cvb.setStart(input.getPosition()); int ch; while (true) { ISubstitution s = parser.getCVB(input); if (s != null) { s.readMe(input, parser); cvb.add(s); if (s instanceof TclElement) { cvb.setEnd(((TclElement) s).getEnd()); } } else { ch = input.read(); if (ch == ICodeScanner.EOF) { boolean cont = parser .handleError(new ErrorDescription( Messages.VariableSubstitution_VariableIndex, getStart(), input.getPosition(), ErrorDescription.ERROR)); if (!cont) throw new TclParseException( Messages.VariableSubstitution_VariableIndex, getStart()); else break; // stop! } if (ch == ')') { if (input.isEOF()) { cvb.setEnd(input.getPosition() - 1); } else { cvb.setEnd(input.getPosition() - 2); } break; } else { cvb.add((char) ch); cvb.setEnd(input.getPosition()); } } } this.index = cvb; break; } else { input.unread(); break; } } } while (true); } if (!input.isEOF()) { setEnd(input.getPosition() - 1); } else setEnd(input.getPosition()); return true; } public int getKind() { return kind; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()).append("["); //$NON-NLS-1$ sb.append("$"); //$NON-NLS-1$ if (kind == VAR_NAME) { sb.append("{"); //$NON-NLS-1$ } sb.append(name); if (kind == VAR_NAME) { sb.append("}"); //$NON-NLS-1$ } if (index != null) { sb.append("("); //$NON-NLS-1$ sb.append(index); sb.append(")"); //$NON-NLS-1$ } sb.append("]"); //$NON-NLS-1$ return sb.toString(); } }