/*
* ProductionPattern.cs
*
* This work 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 2 of the License,
* or (at your option) any later version.
*
* This work 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* As a special exception, the copyright holders of this library give
* you permission to link this library with independent modules to
* produce an executable, regardless of the license terms of these
* independent modules, and to copy and distribute the resulting
* executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the
* license of that module. An independent module is a module which is
* not derived from or based on this library. If you modify this
* library, you may extend this exception to your version of the
* library, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Copyright (c) 2003 Per Cederberg. All rights reserved.
*/
using System.Collections;
using System.Text;
namespace PerCederberg.Grammatica.Parser {
/**
* A production pattern. This class represents a set of production
* alternatives that together forms a single production. A
* production pattern is identified by an integer id and a name,
* both provided upon creation. The pattern id is used for
* referencing the production pattern from production pattern
* elements.
*
* @author Per Cederberg, <per at percederberg dot net>
* @version 1.0
*/
public class ProductionPattern {
/**
* The production pattern identity.
*/
private int id;
/**
* The production pattern name.
*/
private string name;
/**
* The syntectic production flag. If this flag is set, the
* production identified by this pattern has been artificially
* inserted into the grammar.
*/
private bool syntetic;
/**
* The list of production pattern alternatives.
*/
private ArrayList alternatives;
/**
* The default production pattern alternative. This alternative
* is used when no other alternatives match. It may be set to
* -1, meaning that there is no default (or fallback) alternative.
*/
private int defaultAlt;
/**
* The look-ahead set associated with this pattern.
*/
private LookAheadSet lookAhead;
/**
* Creates a new production pattern.
*
* @param id the production pattern id
* @param name the production pattern name
*/
public ProductionPattern(int id, string name) {
this.id = id;
this.name = name;
this.syntetic = false;
this.alternatives = new ArrayList();
this.defaultAlt = -1;
this.lookAhead = null;
}
/**
* Checks if the syntetic production flag is set. If this flag
* is set, the production identified by this pattern has been
* artificially inserted into the grammar. No parse tree nodes
* will be created for such nodes, instead the child nodes
* will be added directly to the parent node.
*
* @return true if this production pattern is syntetic, or
* false otherwise
*/
public bool IsSyntetic() {
return syntetic;
}
/**
* Checks if this pattern is recursive on the left-hand side.
* This method checks if any of the production pattern
* alternatives is left-recursive.
*
* @return true if at least one alternative is left recursive, or
* false otherwise
*/
public bool IsLeftRecursive() {
ProductionPatternAlternative alt;
for (int i = 0; i < alternatives.Count; i++) {
alt = (ProductionPatternAlternative) alternatives[i];
if (alt.IsLeftRecursive()) {
return true;
}
}
return false;
}
/**
* Checks if this pattern is recursive on the right-hand side.
* This method checks if any of the production pattern
* alternatives is right-recursive.
*
* @return true if at least one alternative is right recursive, or
* false otherwise
*/
public bool IsRightRecursive() {
ProductionPatternAlternative alt;
for (int i = 0; i < alternatives.Count; i++) {
alt = (ProductionPatternAlternative) alternatives[i];
if (alt.IsRightRecursive()) {
return true;
}
}
return false;
}
/**
* Checks if this pattern would match an empty stream of
* tokens. This method checks if any one of the production
* pattern alternatives would match the empty token stream.
*
* @return true if at least one alternative match no tokens, or
* false otherwise
*/
public bool IsMatchingEmpty() {
ProductionPatternAlternative alt;
for (int i = 0; i < alternatives.Count; i++) {
alt = (ProductionPatternAlternative) alternatives[i];
if (alt.IsMatchingEmpty()) {
return true;
}
}
return false;
}
/**
* Returns the unique production pattern identity value.
*
* @return the production pattern id
*/
public int GetId() {
return id;
}
/**
* Returns the production pattern name.
*
* @return the production pattern name
*/
public string GetName() {
return name;
}
/**
* Sets the syntetic production pattern flag. If this flag is set,
* the production identified by this pattern has been artificially
* inserted into the grammar. By default this flag is set to
* false.
*
* @param syntetic the new value of the syntetic flag
*/
public void SetSyntetic(bool syntetic) {
this.syntetic = syntetic;
}
/**
* Returns the number of alternatives in this pattern.
*
* @return the number of alternatives in this pattern
*/
public int GetAlternativeCount() {
return alternatives.Count;
}
/**
* Returns an alternative in this pattern.
*
* @param pos the alternative position, 0 <= pos < count
*
* @return the alternative found
*/
public ProductionPatternAlternative GetAlternative(int pos) {
return (ProductionPatternAlternative) alternatives[pos];
}
/**
* Adds a production pattern alternative.
*
* @param alt the production pattern alternative to add
*
* @throws ParserCreationException if an identical alternative has
* already been added
*/
public void AddAlternative(ProductionPatternAlternative alt) {
if (alternatives.Contains(alt)) {
throw new ParserCreationException(
ParserCreationException.ErrorType.INVALID_PRODUCTION,
name,
"two identical alternatives exist");
}
alt.SetPattern(this);
alternatives.Add(alt);
}
/**
* Returns a string representation of this object.
*
* @return a token string representation
*/
public override string ToString() {
StringBuilder buffer = new StringBuilder();
StringBuilder indent = new StringBuilder();
int i;
buffer.Append(name);
buffer.Append("(");
buffer.Append(id);
buffer.Append(") ");
for (i = 0; i < buffer.Length; i++) {
indent.Append(" ");
}
for (i = 0; i < alternatives.Count; i++) {
if (i == 0) {
buffer.Append("= ");
} else {
buffer.Append("\n");
buffer.Append(indent);
buffer.Append("| ");
}
buffer.Append(alternatives[i]);
}
return buffer.ToString();
}
/**
* Returns the look-ahead set associated with this alternative.
*
* @return the look-ahead set associated with this alternative
*/
internal LookAheadSet GetLookAhead() {
return lookAhead;
}
/**
* Sets the look-ahead set for this alternative.
*
* @param lookAhead the new look-ahead set
*/
internal void SetLookAhead(LookAheadSet lookAhead) {
this.lookAhead = lookAhead;
}
/**
* Returns the default pattern alternative. The default
* alternative is used when no other alternative matches.
*
* @return the default pattern alternative, or
* null if none has been set
*/
internal ProductionPatternAlternative GetDefaultAlternative() {
if (defaultAlt >= 0) {
object obj = alternatives[defaultAlt];
return (ProductionPatternAlternative) obj;
} else {
return null;
}
}
/**
* Sets the default pattern alternative. The default alternative
* is used when no other alternative matches.
*
* @param pos the position of the default alternative
*/
internal void SetDefaultAlternative(int pos) {
if (pos >= 0 && pos < alternatives.Count) {
this.defaultAlt = pos;
}
}
}
}