/******************************************************************************* * Copyright (c) 2009 xored software, Inc. * * 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 (Vladimir Belov) *******************************************************************************/ package org.eclipse.dltk.javascript.parser; import org.antlr.runtime.CharStream; import org.antlr.runtime.MismatchedTokenException; import org.antlr.runtime.RecognitionException; public class JavaScriptTokenSource extends JavaScriptLexer implements JSTokenSource { public JavaScriptTokenSource(CharStream input) { super(input); } @Override protected boolean isXmlStartEnabled() { // TODO return ((JSTokenSource) this).getMode() == JSTokenSource.MODE_JS && areRegularExpressionsEnabled(); } private int xmlMode = MODE_JS; public int getMode() { return xmlMode; } public void setMode(int mode) { this.xmlMode = mode; } public void seek(int index) { input.seek(index); } @Override public void mTokens() throws RecognitionException { if (xmlMode == MODE_XML) { readNextXml(); } else if (xmlMode == MODE_EXPRESSION) { try { super.mTokens(); } catch (RecognitionException e) { recover(e); type = XMLFragmentError; emit(); } } else { super.mTokens(); } } private int xmlOpenTagsCount; @SuppressWarnings("unused") private boolean xmlIsAttribute; private boolean xmlIsTagContent; @Override protected void readFirstXml() throws RecognitionException { assert xmlMode == MODE_JS; xmlOpenTagsCount = 0; xmlIsAttribute = false; xmlIsTagContent = false; readNextXml(); } private void readNextXml() { try { type = readXmlToken(); emit(); } catch (LexerException e) { type = XMLFragmentError; emit(); } } private int readXmlToken() { int c; while ((c = input.LA(1)) != EOF) { if (xmlIsTagContent) { switch (c) { case '>': matchAny(); xmlIsTagContent = false; xmlIsAttribute = false; break; case '/': matchAny(); if (input.LA(1) == '>') { matchAny(); xmlIsTagContent = false; xmlOpenTagsCount--; } break; case '{': // matchAny(); return XMLFragment; case '\'': case '\"': matchAny(); readQuotedString(c); break; case '=': matchAny(); xmlIsAttribute = true; break; case ' ': case '\t': case '\r': case '\n': matchAny(); break; default: matchAny(); xmlIsAttribute = false; break; } if (!xmlIsTagContent && xmlOpenTagsCount == 0) { return XMLFragmentEnd; } } else { switch (c) { case '<': matchAny(); switch (input.LA(1)) { case '!': matchAny(); switch (input.LA(1)) { case '-': matchAny(); if (input.LA(1) == '-') { matchAny(); readXmlComment(); } else { throw new LexerException("msg.XML.bad.form"); } break; case '[': matchAny(); try { match("CDATA["); } catch (MismatchedTokenException e) { throw new LexerException("CDATA[ expected"); } readCDATA(); break; default: readEntity(); break; } break; case '?': matchAny(); readPI(); break; case '/': // End tag matchAny(); if (xmlOpenTagsCount == 0) { throw new LexerException("msg.XML.bad.form"); } xmlIsTagContent = true; xmlOpenTagsCount--; break; default: // Start tag xmlIsTagContent = true; xmlOpenTagsCount++; break; } // / break; case '{': // matchAny(); return XMLFragment; default: matchAny(); break; } } } throw new LexerException("msg.XML.bad.form"); } private void readQuotedString(int quote) { int c; while ((c = input.LA(1)) != EOF) { matchAny(); if (c == quote) { return; } } throw new LexerException("msg.XML.bad.form"); } private void readXmlComment() { int c; while ((c = input.LA(1)) != EOF) { matchAny(); if (c == '-' && input.LA(1) == '-' && input.LA(2) == '>') { return; } } throw new LexerException("msg.XML.bad.form"); } private void readCDATA() { int c; while ((c = input.LA(1)) != EOF) { matchAny(); if (c == ']' && input.LA(1) == ']' && input.LA(2) == '>') return; } throw new LexerException("msg.XML.bad.form"); } private void readEntity() { int declTags = 1; int c; while ((c = input.LA(1)) != EOF) { matchAny(); switch (c) { case '<': declTags++; break; case '>': declTags--; if (declTags == 0) return; break; } } throw new LexerException("msg.XML.bad.form"); } private void readPI() { int c; while ((c = input.LA(1)) != EOF) { matchAny(); if (c == '?' && input.LA(1) == '>') { matchAny(); return; } } throw new LexerException("msg.XML.bad.form"); } @SuppressWarnings("serial") private static class LexerException extends RuntimeException { public LexerException(String message) { super(message); } } }