/******************************************************************************* * Copyright (c) 2007, 2010 Borland Software Corporation 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: * Borland Software Corporation - initial API and implementation * Alex Paperno - bugs 416584 *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.ast.parser; import java.io.Reader; import org.eclipse.emf.ecore.EObject; import org.eclipse.m2m.internal.qvt.oml.NLS; import org.eclipse.m2m.internal.qvt.oml.ast.env.QVTParsingOptions; import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv; import org.eclipse.m2m.internal.qvt.oml.compiler.CompilerMessages; import org.eclipse.m2m.internal.qvt.oml.cst.CSTFactory; import org.eclipse.m2m.internal.qvt.oml.cst.UnitCS; import org.eclipse.m2m.internal.qvt.oml.cst.parser.AbstractQVTParser; import org.eclipse.m2m.internal.qvt.oml.cst.parser.QVTOLexer; import org.eclipse.m2m.internal.qvt.oml.cst.parser.QVTOParser; import org.eclipse.ocl.OCLInput; import org.eclipse.ocl.ParserException; import com.ibm.icu.lang.UCharacter; public class QvtOperationalParser { public QvtOperationalParser() { } public static QVTOLexer createLexer(final Reader is, final String name, QvtOperationalEnv env) throws ParserException { QVTOLexer lexer = new QVTOLexer(env, correctLineBreaks(new OCLInput(is)), name, 4); return lexer; } public UnitCS parse(final Reader is, final String name, QvtOperationalEnv env) { UnitCS result = null; int sourceLength = 0; // Note: // Adding compilation unit here to support multiple top-level elements // Before they get supported already by the raw parser, // the compiler and the rest of the tooling can adopt it try { QVTOLexer lexer = createLexer(is, name, env); myParser = new RunnableQVTParser(lexer); myParser.enableCSTTokens(Boolean.TRUE.equals(env.getValue(QVTParsingOptions.ENABLE_CSTMODEL_TOKENS))); lexer.lexer(myParser.getIPrsStream()); result = (UnitCS) myParser.runParser(-1); sourceLength = lexer.getILexStream().getStreamLength(); } catch (ParserException ex) { env.reportError(ex.getLocalizedMessage(), 0, 0); } if (result == null) { if (!env.hasErrors()) { env.reportError(NLS.bind( CompilerMessages.moduleTransformationExpected, new Object[] { name }),0, 0); } result = CSTFactory.eINSTANCE.createUnitCS(); } result.setStartOffset(0); result.setEndOffset(sourceLength); return result; } /* public Module analyze(AbstractQVTParser parser, final MappingModuleCS moduleCS, ExternalUnitElementsProvider importResolver, ResourceSet resSet, QvtOperationalFileEnv env, QvtCompilerOptions options) { Module module = null; env.setQvtCompilerOptions(options); try { QvtOperationalVisitorCS visitor = new QvtOperationalVisitorCS(parser, options); module = visitor.visitMappingModule(moduleCS, importResolver.getImporter(), env, importResolver, resSet); } catch (SemanticException e) { env.reportError(e.getLocalizedMessage(), 0, 0); } if (module != null && options.isReportErrors()) { env.setCheckForDuplicateErrors(true); QvtOperationalValidationVisitor validation = new QvtOperationalValidationVisitor(env); validation.visitModule(module); env.setCheckForDuplicateErrors(false); } return module; } */ private class RunnableQVTParser extends QVTOParser { public RunnableQVTParser(QVTOLexer lexStream) { super(lexStream); } public EObject runParser(int max_error_count) throws ParserException { return parser(max_error_count); } // @Override // protected void OnParseError(BadParseException e) { // super.OnParseError(e); // } // // @Override // public void reportError(int errorCode, int leftToken, int rightToken, String tokenText) { // super.reportError(errorCode, leftToken, rightToken, tokenText); // } // FIXME - OCL 1.2 migration, workaround for ArrayIndexOutBounds @Override public String computeInputString(int left, int right) { char[] chars = getIPrsStream().getInputChars(); if(right < left) { right = left; } if(right >= chars.length) { right = chars.length - 1; } StringBuffer result = new StringBuffer(right - left + 1); if (chars.length > 0) { for (int i = left; i <= right; i++) { if (chars[i] == '\t') { result.append(' '); } else if (chars[i] == '\n' || chars[i] == '\r' || chars[i] == '\f') { if (i > 0) { if (!UCharacter.isWhitespace(chars[i-1])) { result.append(' '); } } } else { result.append(chars[i]); } } } return result.toString(); } } public AbstractQVTParser getParser() { return myParser; } // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=259486 private static char[] correctLineBreaks(OCLInput input) throws ParserException { char[] contents = input.getContentAsString().toCharArray(); for (int i = 0; i < contents.length; i++) { char c = contents[i]; // check for single '\n' characters when MAC line breaks are used if(c == '\r') { // possibly the MAC new line char CR, check if not followed by LF, // as CR/LF is the newline on windows int nextPos = i + 1; if(nextPos == contents.length || contents[nextPos] != '\n') { // we found a single CR, consider it a line separator contents[i] = '\n'; } } } return contents; } private RunnableQVTParser myParser; }