blob: fe4940cc4be496e1634bf43181afe0a6129095c0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2006 IBM 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.gymnast.generators.parser.antlr;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.eclipse.gymnast.generator.core.ast.AltRule;
import org.eclipse.gymnast.generator.core.ast.Alts;
import org.eclipse.gymnast.generator.core.ast.GymnastASTNodeVisitor;
import org.eclipse.gymnast.generator.core.ast.HeaderSection;
import org.eclipse.gymnast.generator.core.ast.ListRule;
import org.eclipse.gymnast.generator.core.ast.OptSubSeq;
import org.eclipse.gymnast.generator.core.ast.Option;
import org.eclipse.gymnast.generator.core.ast.Rule;
import org.eclipse.gymnast.generator.core.ast.SeqRule;
import org.eclipse.gymnast.generator.core.ast.SimpleExpr;
import org.eclipse.gymnast.generator.core.ast.TokenRule;
import org.eclipse.gymnast.generator.core.generator.ASTUtil;
import org.eclipse.gymnast.generator.core.generator.GeneratorContext;
import org.eclipse.gymnast.generator.core.generator.GeneratorUtil;
import org.eclipse.gymnast.generator.core.generator.GrammarInfo;
import org.eclipse.gymnast.generator.core.generator.RuleRefCollector;
/**
* @author cjdaly@us.ibm.com
*
*/
public class AntlrGrammarWriter extends GymnastASTNodeVisitor {
private GeneratorContext _context;
private GeneratorUtil _util;
private GrammarInfo _grammarInfo;
private StringBuffer _buffer;
public AntlrGrammarWriter(GeneratorContext context) {
_context = context;
_util = context.getUtil();
_grammarInfo = _context.getGrammarInfo();
}
public StringBuffer writeGrammar() {
_buffer = new StringBuffer();
this.visit(_context.getCompUnit());
return _buffer;
}
public boolean beginVisit(HeaderSection headerSection) {
writeln();
writeln("header");
writeln("{");
writeln("package " + _context.getParserPackageName() + ";");
writeln("import " + _context.getASTPackageName() + ".*;");
writeln("import " + _context.getLDT_ParserPackageName() + ".*;");
writeln("import " + _context.getLDT_ASTNodePackageName() + ".*;");
writeln("}");
writeln();
writeln("class " + headerSection.getName().getText() + "Parser extends Parser;");
writeln();
if (headerSection.getOptionsSection() != null) {
writeln("options {");
new GymnastASTNodeVisitor() {
public boolean beginVisit(Option option) {
String optionName = option.getName().getText();
if (isValidAntlrOption(optionName)) {
write(" " + optionName);
write("=" + option.getValue().getText());
writeln(";");
writeln();
}
return false;
}
private boolean isValidAntlrOption(String optionName) {
// TODO: compile exhaustive list
if ("k".equals(optionName)) return true;
return false;
}
}.visit(headerSection.getOptionsSection().getOptionList());
writeln("}");
}
writeln("{"); // begin inline Java
writeln(" private ParseError createParseError(RecognitionException ex) {");
writeln(" return " + headerSection.getName().getText() + "ParserDriver.createParseError(ex);");
writeln(" }");
writeln();
writeln(" private TokenInfo createTokenInfo(Token tok) {");
writeln(" if (tok == null) return null;");
writeln(" else return new TokenInfo(tok.getText(), tok.getColumn(), tok.getType());");
writeln(" }");
writeln();
writeErrorHandlers();
writeln("}"); // end inline Java
writeln();
return true;
}
public boolean beginVisit(AltRule rule) {
String ruleName = ASTUtil.getName(rule);
String typeName = _util.toUppercaseName(ruleName);
String returnParamName = getReturnParamName(rule);
writeDecl(rule, ruleName, typeName, returnParamName, false);
writeln(":");
writeJavaDecls(rule);
return true;
}
public boolean beginVisit(Alts alts) {
AltRule rule = (AltRule)alts.getParent().getParent();
String returnParamName = getReturnParamName(rule);
if (rule.getBody().getPreSeq() != null) writeln();
write(" ( ");
for (int i = 0; i < alts.getChildCount(); i+=2) {
SimpleExpr se = (SimpleExpr)alts.getChild(i);
if (i > 0) write(" | ");
write(returnParamName);
write("=");
String refRuleName = se.getValue().getText();
write(refRuleName);
RuleRefCollector refs = _grammarInfo.getRuleRefCollector(rule);
Rule altRule = _grammarInfo.getRule(refRuleName);
RuleRefCollector altRefs = _grammarInfo.getRuleRefCollector(altRule);
if (altRefs.getInheritedLabelCount() > 0) {
write("[");
String[] labels = altRefs.getLabels();
for (int j = 0; j < altRefs.getInheritedLabelCount(); j++) {
String label = labels[j];
if (j > 0) write(", ");
if (refs.hasLabel(label)) write(label);
else write("null");
}
write("]");
}
writeln();
}
writeln(" )");
return false;
}
public void endVisit(AltRule rule) {
writeln(";");
writeln();
}
public boolean beginVisit(ListRule rule) {
String ruleName = ASTUtil.getName(rule);
String typeName = _util.toUppercaseName(ruleName);
String returnParamName = getReturnParamName(rule);
writeDecl(rule, ruleName, typeName, returnParamName, true);
writeln(":");
writeJavaDecls(rule);
SimpleExpr listExpr = rule.getBody().getListExpr();
if (rule.getBody().getLparen() == null) {
write(" ( ");
write(listExpr);
write(" { ");
write(returnParamName + ".addChild(" + getAddChildExpression(listExpr) + ");");
write(" } ");
write(")");
write(rule.getBody().getListMark().getText());
if (ASTUtil.hasAttr(rule, "entry")) {
write(" EOF");
}
writeln();
}
else {
write(" ");
write(listExpr);
write(" { ");
write(returnParamName + ".addChild(" + getAddChildExpression(listExpr) + ");");
write(" } ");
writeln();
SimpleExpr separator = rule.getBody().getSeparator();
SimpleExpr listExpr2 = rule.getBody().getListExpr2();
write(" ( ");
write(separator);
write(" ");
write(listExpr2);
write(" { ");
write(returnParamName + ".addChild(" + getAddChildExpression(separator) + "); ");
write(returnParamName + ".addChild(" + getAddChildExpression(listExpr2) + ");");
write(" } ");
write(")");
write(rule.getBody().getListMark().getText());
if (ASTUtil.hasAttr(rule, "entry")) {
write(" EOF");
}
writeln();
}
writeln(";");
writeln();
return false;
}
private String getAddChildExpression(SimpleExpr listExpr) {
String listExprRule = listExpr.getValue().getText();
if (_util.isTokenReference(listExprRule)) {
return "createTokenInfo(" + _util.getLabel(listExpr) + ")";
}
else {
return _util.getLabel(listExpr);
}
}
public boolean beginVisit(SeqRule rule) {
String ruleName = ASTUtil.getName(rule);
String typeName = _util.toUppercaseName(ruleName);
String returnParamName = getReturnParamName(rule);
writeDecl(rule, ruleName, typeName, returnParamName, false);
writeln(":");
writeJavaDecls(rule);
write(" ");
return true;
}
public void endVisit(SeqRule rule) {
String ruleName = ASTUtil.getName(rule);
String typeName = _util.toUppercaseName(ruleName);
String returnParamName = getReturnParamName(rule);
if (ASTUtil.hasAttr(rule, "entry")) {
write("EOF");
}
writeln();
write("{ " + returnParamName + " = new " + typeName + "(");
RuleRefCollector refs = _grammarInfo.getRuleRefCollector(rule);
String[] labels = refs.getLabels();
for (int i = 0; i < labels.length; i++) {
String label = labels[i];
String type = refs.getType(label);
String ref;
if (_util.isTokenReference(type)) {
ref = "createTokenInfo(" + label + ")";
}
else {
ref = label;
}
if (i == 0) write(ref);
else write(", " + ref);
}
writeln("); }");
writeln(";");
writeln();
}
public boolean beginVisit(TokenRule rule) {
String ruleName = ASTUtil.getName(rule);
String typeName = _util.toUppercaseName(ruleName);
String returnParamName = getReturnParamName(rule);
writeDecl(rule, ruleName, typeName, returnParamName, false);
writeln("{ Token tok = LT(1); }");
write (": ( ");
Alts alts = rule.getBody();
for (int i = 0; i < alts.getChildCount(); i+=2) {
SimpleExpr se = (SimpleExpr)alts.getChild(i);
if (i == 0) writeln(se.getValue().getText());
else writeln(" | " + se.getValue().getText());
}
writeln(" )");
writeln("{ " + returnParamName + " = new " + typeName + "(createTokenInfo(tok)); }");
writeln(";");
writeln();
return false;
}
public boolean beginVisit(OptSubSeq optSubSeq) {
write("( ");
return true;
}
public void endVisit(OptSubSeq optSubSeq) {
write(")? ");
}
public boolean beginVisit(SimpleExpr simpleExpr) {
write(simpleExpr);
write(" ");
return false;
}
private void writeErrorHandlers() {
try {
InputStream input = this.getClass().getResourceAsStream("ErrorHandlers.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line = reader.readLine();
while(line != null) {
writeln(line);
line = reader.readLine();
}
}
catch (IOException ex) {
_util.reportError(ex);
}
}
private void writeDecl(Rule rule, String ruleName, String typeName, String returnParamName, boolean callCtor) {
write(ruleName);
RuleRefCollector refs = _grammarInfo.getRuleRefCollector(rule);
if (refs.getInheritedLabelCount() > 0) {
write(" [ ");
String[] labels = refs.getLabels();
for (int i = 0; i < refs.getInheritedLabelCount(); i++) {
String label = labels[i];
String type = _util.toUppercaseName(refs.getType(label));
if (_util.isTokenReference(type)) {
type = "TokenInfo";
}
if (i > 0) write(", ");
write(type + " " + label);
}
write(" ] ");
}
String ctor = null;
if (callCtor) ctor = "new " + typeName + "()";
else ctor = "null";
writeln(" returns [ " + typeName + " " + returnParamName + " = " + ctor + " ]");
}
private void writeJavaDecls(Rule rule) {
RuleRefCollector refs = _grammarInfo.getRuleRefCollector(rule);
boolean foundDecl = false;
String[] labels = refs.getLabels();
for (int i = 0; i < labels.length; i++) {
String label = labels[i];
String type = _util.toUppercaseName(refs.getType(label));
if (!_util.isTokenReference(type) && !refs.isInherited(label))
{
if (!foundDecl) {
write("{ ");
foundDecl = true;
}
write(type + " " + label + " = null; ");
}
}
if (foundDecl) writeln("}");
}
private void write(SimpleExpr simpleExpr) {
String rule = simpleExpr.getValue().getText();
String label = _util.getLabel(simpleExpr);
if (_util.isTokenReference(rule)) {
write(label + ":" + rule);
}
else {
write(label + "=" + rule);
}
}
private String getReturnParamName(Rule rule) {
return "retVal";
}
//
//
//
private void write(String s) {
_buffer.append(s);
}
private void writeln() {
write("\n");
}
private void writeln(String s) {
write(s);
writeln();
}
}