/* * * Copyright 2012 lexergen. * This file is part of lexergen. * * lexergen is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * lexergen 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with lexergen. If not, see <http://www.gnu.org/licenses/>. * * lexergen: * A tool to chunk source code into tokens for further processing in a compiler chain. * * Projectgroup: bi, bii * * Authors: Johannes Dahlke * * Module: Softwareprojekt Übersetzerbau 2012 * * Created: Apr. 2012 * Version: 1.0 * */ package de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.grammar; import java.io.Serializable; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import de.fuberlin.bii.utils.Test; /** * Stellt eine Produktionsregel dar. * * @author Johannes Dahlke * */ @SuppressWarnings("rawtypes") public class ProductionRule implements Iterable<RuleElement>, Serializable { private static final long serialVersionUID = 652665932709829362L; private Nonterminal leftRuleSide; private RuleElementSequenz rightRuleSide; public ProductionRule(Nonterminal leftRuleSide, RuleElementSequenz rightRuleSide) { super(); this.leftRuleSide = leftRuleSide; if (Test.isAssigned(rightRuleSide) && rightRuleSide.size() > 0) { this.rightRuleSide = filterEmptyStrings(rightRuleSide); } else { this.rightRuleSide = new RuleElementArray(); this.rightRuleSide.add(new EmptyString()); } } public ProductionRule(Nonterminal leftRuleSide, final RuleElement... rightRuleSideElements) { this(leftRuleSide, new RuleElementArray() { private static final long serialVersionUID = -8519909723287300646L; RuleElementArray getFilledArray() { RuleElementArray ruleElementArray = new RuleElementArray(); ruleElementArray.addAll(Arrays.asList(rightRuleSideElements)); return ruleElementArray; } }.getFilledArray()); } private static RuleElementSequenz filterEmptyStrings(RuleElementSequenz elementSequenz) { int len = elementSequenz.size(); for (int i = len - 1; i > 0; i--) { if (elementSequenz.get(i) instanceof EmptyString) elementSequenz.remove(i); } return elementSequenz; } /** * Liefert die linke Regelseite. * @return */ public Nonterminal getLeftRuleSide() { return leftRuleSide; } protected boolean isRightSideRuleEmpty() { boolean result = true; for (RuleElement ruleElement : rightRuleSide) { result &= (ruleElement instanceof EmptyString); } return result; } protected int rightSideRuleSize() { int result = 0; for (RuleElement ruleElement : rightRuleSide) { result += (ruleElement instanceof EmptyString) ? 0 : 1; } return result; } /** * Liefert die rechte Regelseite. * * @return */ public RuleElementSequenz getRightRuleSide() { return rightRuleSide; } public Iterator<RuleElement> iterator() { return rightRuleSide.iterator(); } /** * Liefert die Menge der Elemente auf der rechten Regelseite. * @return */ public Set<RuleElement> getRuleElementSet() { Set<RuleElement> result = new HashSet<RuleElement>(); result.add(leftRuleSide); for (RuleElement ruleElement : this) { result.add(ruleElement); } return result; } /** * Liefert die Menge aller Terminale der rechten Regelseite. * @return */ public Set<Terminal> getTerminalSet() { Set<Terminal> result = new HashSet<Terminal>(); for (RuleElement ruleElement : this) { if ( ruleElement instanceof Terminal) result.add((Terminal)ruleElement); } return result; } /** * Liefert die Menge aller Nichtterminale der rechten Regelseite sowie der linken Regelseite. * @return */ public Set<Nonterminal> getNonterminalSet() { Set<Nonterminal> result = new HashSet<Nonterminal>(); result.add(leftRuleSide); for (RuleElement ruleElement : this) { if ( ruleElement instanceof Nonterminal) result.add((Nonterminal)ruleElement); } return result; } @Override public boolean equals(Object theOtherObject) { if (Test.isUnassigned(theOtherObject)) return false; if (!(theOtherObject instanceof ProductionRule)) return false; ProductionRule theOtherProductionRule = (ProductionRule) theOtherObject; if (!theOtherProductionRule.getLeftRuleSide().equals(this.leftRuleSide)) return false; if (!theOtherProductionRule.getRightRuleSide().equals( this.rightRuleSide)) return false; return true; } @Override public int hashCode() { int hashCode = 5; hashCode = 31 * hashCode + leftRuleSide.hashCode(); hashCode = 31 * hashCode + rightRuleSide.hashCode(); return hashCode; } @Override public String toString() { String result = getLeftRuleSide().toString() + " -> "; for( int i = 0; i < getRightRuleSide().size(); i++) { result += getRightRuleSide().get(i).toString(); } return result; } }