/*******************************************************************************
* Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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
*******************************************************************************/
package com.github.jknack.antlr4ide.parser.antlr;
import java.io.File;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.xpand2.XpandExecutionContext;
import org.eclipse.xtext.Grammar;
import org.eclipse.xtext.generator.BindFactory;
import org.eclipse.xtext.generator.Binding;
import org.eclipse.xtext.generator.Generator;
import org.eclipse.xtext.generator.IGeneratorFragment;
import org.eclipse.xtext.generator.parser.antlr.ex.ca.ContentAssistParserGeneratorFragment;
import org.eclipse.xtext.generator.parser.antlr.ex.common.KeywordHelper;
import com.google.common.collect.ImmutableList;
/**
* A {@link IGeneratorFragment} to generate a lightweight AntLR based parser used in content assist.
*
* @author Sebastian Zarnekow - Initial contribution and API
*/
public class AntlrUiGeneratorFragmentWithCustomLexer extends BaseAntlrGeneratorFragmentEx {
private boolean partialParsing;
/**
* Whether to use a partial parsing approach, improving performance for large files.
* This will generally not work for grammars containing unordered groups.
*
* @since 2.7
*/
public void setPartialParsing(final boolean partialParsing) {
this.partialParsing = partialParsing;
}
/**
* @since 2.7
*/
public boolean isPartialParsing() {
return partialParsing;
}
@Override
public void generate(final Grammar grammar, final XpandExecutionContext ctx) {
KeywordHelper helper = new KeywordHelper(grammar, getOptions().isIgnoreCase());
super.generate(grammar, ctx);
final String srcGenPath = ctx.getOutput().getOutlet(Generator.SRC_GEN_UI).getPath();
final String encoding = getEncoding(ctx, Generator.SRC_GEN_UI);
String libPath = srcGenPath + "/"
+ getFragmentHelper().getContentAssistLexerGrammarFileName(grammar).replace('.', '/');
libPath = libPath.substring(0, libPath.lastIndexOf('/'));
String absoluteLexerFileName = srcGenPath + "/"
+ getFragmentHelper().getContentAssistLexerGrammarFileName(grammar).replace('.', '/')
+ ".g";
String absoluteParserFileName = srcGenPath + "/"
+ getFragmentHelper().getContentAssistParserGrammarFileName(grammar).replace('.', '/')
+ ".g";
addAntlrParam("-fo");
addAntlrParam(absoluteParserFileName.substring(0, absoluteParserFileName.lastIndexOf('/')));
String[] lexerAntlrParams = getAntlrParams();
lexerAntlrParams[lexerAntlrParams.length - 1] = absoluteLexerFileName.substring(0,
absoluteLexerFileName.lastIndexOf('/'));
// copy
copy(new File(absoluteLexerFileName), new File(absoluteLexerFileName.replace(".g", ".gxtext")));
writeFile(
absoluteLexerFileName,
readFile("../antlr4ide.core/src/main/java/com/github/jknack/parser/antlr/lexer/InternalAntlr4Lexer.g"));
getAntlrTool().runWithEncodingAndParams(absoluteLexerFileName, encoding, lexerAntlrParams);
addAntlrParam("-lib");
addAntlrParam(libPath);
getAntlrTool().runWithEncodingAndParams(absoluteParserFileName, encoding, getAntlrParams());
Charset charset = Charset.forName(encoding);
simplifyUnorderedGroupPredicatesIfRequired(grammar, absoluteParserFileName, charset);
splitParserAndLexerIfEnabled(absoluteLexerFileName, absoluteParserFileName, charset);
suppressWarnings(absoluteLexerFileName, absoluteParserFileName, charset);
normalizeLineDelimiters(absoluteLexerFileName, absoluteParserFileName, charset);
normalizeTokens(absoluteLexerFileName, charset);
normalizeTokens(absoluteParserFileName, charset);
helper.discardHelper(grammar);
}
@Override
public Set<Binding> getGuiceBindingsUi(final Grammar grammar) {
BindFactory binder = new BindFactory()
.addTypeToType(
"org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext.Factory",
"org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory")
.addTypeToType(
"org.eclipse.xtext.ui.editor.contentassist.antlr.IContentAssistParser",
getFragmentHelper().getContentAssistParserClassName(grammar))
.addConfiguredBinding(
"ContentAssistLexerProvider",
"binder.bind(" + getFragmentHelper().getInternalContentAssistLexerClassName(grammar)
+ ".class)" +
".toProvider(org.eclipse.xtext.parser.antlr.LexerProvider.create("
+ getFragmentHelper().getInternalContentAssistLexerClassName(grammar) + ".class))")
.addConfiguredBinding(
"ContentAssistLexer",
"binder.bind(org.eclipse.xtext.ui.editor.contentassist.antlr.internal.Lexer.class)" +
".annotatedWith(com.google.inject.name.Names.named(" +
"org.eclipse.xtext.ui.LexerUIBindings.CONTENT_ASSIST" +
")).to(" + getFragmentHelper().getInternalContentAssistLexerClassName(grammar)
+ ".class)");
if (partialParsing) {
binder
.addTypeToType(
"org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory.StatefulFactory",
"org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory.PartialStatefulFactory");
}
return binder.getBindings();
}
@Override
public String[] getRequiredBundlesUi(final Grammar grammar) {
return new String[]{"org.antlr.runtime" };
}
@Override
protected String getTemplate() {
return ContentAssistParserGeneratorFragment.class.getName().replaceAll("\\.", "::");
}
@Override
protected List<Object> getParameters(final Grammar grammar) {
return ImmutableList.of(getOptions(), getFragmentHelper(), partialParsing);
}
@Override
protected Map<String, Object> vars() {
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("package", "com.github.jknack.antlr4ide.ui.contentassist.antlr.lexer");
vars.put("lexer", "org.eclipse.xtext.ui.editor.contentassist.antlr.internal.Lexer");
return vars;
}
}