/* * Copyright (C) 2018 Daniel Dietsch (dietsch@informatik.uni-freiburg.de) * Copyright (C) 2018 University of Freiburg * * This file is part of the ULTIMATE Crocotta plug-in. * * The ULTIMATE Crocotta plug-in is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ULTIMATE Crocotta plug-in is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ULTIMATE Crocotta plug-in. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE Crocotta plug-in, or any covered work, by linking * or combining it with Eclipse RCP (or a modified version of Eclipse RCP), * containing parts covered by the terms of the Eclipse Public License, the * licensors of the ULTIMATE Crocotta plug-in grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.crocotta; import java.io.File; import java.io.FileReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import com.github.jhoenicke.javacup.runtime.Symbol; import de.uni_freiburg.informatik.ultimate.core.model.ISource; import de.uni_freiburg.informatik.ultimate.core.model.models.IElement; import de.uni_freiburg.informatik.ultimate.core.model.models.ModelType; import de.uni_freiburg.informatik.ultimate.core.model.preferences.IPreferenceInitializer; import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger; import de.uni_freiburg.informatik.ultimate.core.model.services.IUltimateServiceProvider; import de.uni_freiburg.informatik.ultimate.crocotta.ast.Concatenation; import de.uni_freiburg.informatik.ultimate.crocotta.ast.CrocottaAstVisitor; import de.uni_freiburg.informatik.ultimate.crocotta.ast.Event; import de.uni_freiburg.informatik.ultimate.crocotta.ast.FinInfExpression; import de.uni_freiburg.informatik.ultimate.crocotta.ast.FixpointQuery; import de.uni_freiburg.informatik.ultimate.crocotta.ast.InclusionQuery; import de.uni_freiburg.informatik.ultimate.crocotta.ast.Intersection; import de.uni_freiburg.informatik.ultimate.crocotta.ast.LanguageExpression; import de.uni_freiburg.informatik.ultimate.crocotta.ast.Numeral; import de.uni_freiburg.informatik.ultimate.crocotta.ast.Query; import de.uni_freiburg.informatik.ultimate.crocotta.ast.Union; import de.uni_freiburg.informatik.ultimate.crocotta.parser.CrocParser; public class Crocotta implements ISource { private ILogger mLogger; private final List mFileNames = new ArrayList<>(); private IUltimateServiceProvider mServices; @Override public void init() { // not necessary } @Override public String getPluginName() { return Activator.PLUGIN_NAME; } @Override public String getPluginID() { return Activator.PLUGIN_ID; } @Override public File[] parseable(final File[] files) { final List rtrList = Arrays.stream(files).filter(this::parseable).collect(Collectors.toList()); return rtrList.toArray(new File[rtrList.size()]); } public boolean parseable(final File file) { return Arrays.stream(getFileTypes()).anyMatch(a -> file.getName().endsWith(a)); } @Override public IElement parseAST(final File[] files) throws Exception { if (files == null) { throw new AssertionError(); } if (files.length != 1) { throw new UnsupportedOperationException( "Cannot parse more or less than one .croc file. You supplied " + files.length); } final FileReader reader = new FileReader(files[0]); final CrocParser parser = new CrocParser(mServices, mLogger, reader, files[0].getAbsolutePath()); final Symbol goal = parser.parse(); final Query[] queries = (Query[]) goal.value; for (final Query query : queries) { mLogger.info(new CrocottaQueryPrinter(query)); } // process these queries or make a model out of them return null; } @Override public String[] getFileTypes() { return new String[] { ".croc" }; } @Override public ModelType getOutputDefinition() { try { return new ModelType(getPluginID(), ModelType.Type.AST, mFileNames); } catch (final Exception ex) { mLogger.fatal("syntax error: " + ex.getMessage()); return null; } } @Override public IPreferenceInitializer getPreferences() { return null; } @Override public void setServices(final IUltimateServiceProvider services) { mServices = services; mLogger = services.getLoggingService().getLogger(Activator.PLUGIN_ID); } @Override public void finish() { // not necessary } private class CrocottaQueryPrinter extends CrocottaAstVisitor { private final StringBuilder mBuilder; public CrocottaQueryPrinter() { mBuilder = new StringBuilder(); } public CrocottaQueryPrinter(final Query query) { this(); query.accept(this); } @Override public boolean visit(final Concatenation node) { return printNAryOp("concat", node.getExpr()); } private boolean printNAryOp(final String op, final LanguageExpression[] exprs) { mBuilder.append("(").append(op); Arrays.stream(exprs).forEach(a -> { mBuilder.append(" "); a.accept(this); }); mBuilder.append(")"); return false; } @Override public boolean visit(final Event node) { mBuilder.append("\"").append(node.getName()).append("\""); return false; } @Override public boolean visit(final FinInfExpression node) { mBuilder.append("(pair "); mBuilder.append(node.getFinite()); mBuilder.append(", "); mBuilder.append(node.getInfinite()); mBuilder.append(")"); return false; } @Override public boolean visit(final FixpointQuery node) { mBuilder.append("["); node.getFinInfExpr().accept(this); mBuilder.append(" = "); node.getExpr().accept(this); mBuilder.append("]"); return false; } @Override public boolean visit(final Intersection node) { return printNAryOp("intersect", node.getExpr()); } @Override public boolean visit(final Union node) { return printNAryOp("union", node.getExpr()); } @Override public boolean visit(final Numeral node) { mBuilder.append(node.getValue()); return false; } @Override public boolean visit(final InclusionQuery node) { mBuilder.append("["); node.getLeft().accept(this); mBuilder.append(" <= "); node.getRight().accept(this); mBuilder.append("]"); return super.visit(node); } @Override public String toString() { return mBuilder.toString(); } } }