//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ using System.Text; using System.Collections; using Ilog.Language.Util; namespace Ilog.Language.Syntax { /** * This class is an abstract representation of the type of tokens * that are dynamic operators, whether Operator (used use * by the grammar at parser construction time), or ParserOperator * (used by the parser at parse time). * * @see Symbol * @see Operator * @see Parsing.Operator * * @version Last modified on Tue May 31 13:50:22 2005 by hak * @author Hassan Aït-Kaci * @copyright © 2000 ILOG, S.A. */ public abstract class OperatorSymbol : Symbol { /** * Constructs an operator symbol with the specified name, * reference list, precedence, and specifier. */ public OperatorSymbol (string name, ArrayList list, int precedence, string specifier) // throws NonFatalParseErrorException : base(name,list) { this.precedence = precedence; Decode(specifier); } /** * Constructs an operator symbol with the specified name, * reference list, precedence, associativity, and fixity. */ public OperatorSymbol (string name, ArrayList list, int precedence, int associativity, int fixity) : base(name,list) { this.precedence = precedence; this.associativity = associativity; this.fixity = fixity; } /** Constant denoting an operator quality of being prefix. */ public const int PREFIX = 0; /** Constant denoting an operator quality of being postfix. */ public const int POSTFIX = 1; /** Constant denoting an operator quality of being infix. */ public const int INFIX = 2; /** This operator symbol's nonterminal category name. */ public abstract string CategoryName { get; } /** This operator symbol's precedence. */ protected int precedence; public int Precedence { get { return precedence; } } /** This operator symbol's associativity. */ protected int associativity; public int Associativity { get { return associativity; } } /** This operator symbol's fixity. */ protected int fixity; public int Fixity { get { return fixity; } } /** This operator symbol's associativity/fixity specifier. */ public string Specifier { get { StringBuilder s = new StringBuilder(); if (associativity == Grammar.LEFT_ASSOCIATIVE) s.Append("y"); else if (fixity != PREFIX) s.Append("x"); s.Append("f"); if (associativity == Grammar.RIGHT_ASSOCIATIVE) s.Append("y"); else if (fixity != POSTFIX) s.Append("x"); return s.ToString(); } } /** * Changes the definition of this operator symbol with * the specified precedence and specifier. */ public void Redefine (int precedence, string specifier) // throws NonFatalParseErrorException { this.precedence = precedence; Decode(specifier); } /** * Throws a NonFatalParseErrorException reporting the specified * specifier as bad. */ private void Bad (string specifier) // throws NonFatalParseErrorException { throw new NonFatalParseErrorException ("Bad dynamic operator specifier ("+specifier+")"); } /** * Decodes and interprets the contents of a Prolog-style operator * specifier string. */ private void Decode (string specifier) // throws NonFatalParseErrorException { if (specifier.Length == 2) { if (specifier.IndexOf('f') == 0) { fixity = PREFIX; if (specifier[1] == 'y') { associativity = Grammar.RIGHT_ASSOCIATIVE; return; } if (specifier[1] == 'x') { associativity = Grammar.NON_ASSOCIATIVE; return; } Bad(specifier); } if (specifier.IndexOf('f') == 1) { fixity = POSTFIX; if (specifier[0] == 'y') { associativity = Grammar.LEFT_ASSOCIATIVE; return; } if (specifier[0] == 'x') { associativity = Grammar.NON_ASSOCIATIVE; return; } } Bad(specifier); } if (specifier.Length == 3 && specifier.IndexOf('f') == 1) { fixity = INFIX; if (specifier[0] == 'y') { if (specifier[2] != 'x') Bad(specifier); associativity = Grammar.LEFT_ASSOCIATIVE; return; } if (specifier[0] == 'x') { if (specifier[2] == 'y') associativity = Grammar.RIGHT_ASSOCIATIVE; else if (specifier[2] == 'x') associativity = Grammar.NON_ASSOCIATIVE; else Bad(specifier); return; } } Bad(specifier); } /** * Returns true iff the specified object is an operator symbol * with identical name, category, and fixity. Note that precedence * and associativity are transient properties, in that the same * operator make redefine them without losing its identity. */ public override bool Equals (object other) { if (this == other) return true; if (!(other is OperatorSymbol)) return false; OperatorSymbol that = (OperatorSymbol)other; return this.name == that.name && this.CategoryName == that.CategoryName && this.fixity == that.fixity; } /** * Returns a hash code for this operator symbol. */ public override int GetHashCode () { return name.GetHashCode() ^ CategoryName.GetHashCode() ^ fixity; } /** * Returns a string description for this operator sysmbol. */ public override string ToString () { return CategoryName + "(" + Grammar.PrologPrecedence(precedence) + "," + Specifier + "," + name + ")"; } } }