public Grammar( string name, Expression top,
						ExpBuilder builder, Grammar parent )
            : base(name,top)
        {
            this.Parent = parent;
            this.Builder = builder;
        }
 public static string print( Expression exp, int elemDepth, bool visitRef )
 {
     using( StringWriter str = new StringWriter() ) {
     exp.Visit( new ExpPrinter(str,elemDepth,visitRef) );
     return str.ToString();
     }
 }
	// <a>
	//   <b/><c>...</c><d/>
	// </a>
	// XmlReader should be immediately after reading <a>.
	// When this method returns, it will be immediately after </a>.
	private Expression Verify( Expression contentModel, Expression[] atoms ) {
	
		while(!document.EOF) {
			switch( document.NodeType ) {
			case XmlNodeType.CDATA:
			case XmlNodeType.Text:
			case XmlNodeType.Whitespace:
			case XmlNodeType.SignificantWhitespace:
				OnText();
				break;
			
			case XmlNodeType.Element:
				contentModel = OnElement( contentModel, atoms );
				break;
				
			case XmlNodeType.EndElement:
				return contentModel;
				
			// nodes that are ignored
			case XmlNodeType.Comment:
			case XmlNodeType.ProcessingInstruction:
				document.Read();
				break;
				
			default:
				Console.WriteLine(document.NodeType);
				Debug.Assert(false);
				break;
			}
		}
		
		return contentModel;
	}
 internal DataExp( Datatype _dt, Expression _except, string _name )
     : base(_dt.GetHashCode()*HASH_DATA, false)
 {
     // TODO: probably the epsilon reducibility is wrong.
     // can we treat epsilon-reducibility as an approximation?
     // rather than the precise value?
     this.except = _except;
     this.dt = _dt;
     this.name = _name;
 }
 public ReferenceExp( string name, Expression exp )
     : base(rnd.Next(),false)
 {
     this.name = name;
     this.exp = exp;
 }
        protected virtual void CombineReferenceExp(
				ReferenceExp r, Expression body, string combine )
        {
            if( redefiningRefExps.ContainsKey(r) ) {
            // this pattern is currently being redefined.
            redefiningRefExps[r] = true;
            return;	// ignore the value
            }

            RefParseInfo pi = (RefParseInfo)refParseInfos[r];
            if(pi==null)	refParseInfos[r] = pi = new RefParseInfo();

            if( pi.Combine!=null && combine!=null && pi.Combine!=combine ) {
            // error: inconsistent combine method
            ReportError( ERR_INCONSISTENT_COMBINE, r.name );
            pi.Combine = null;
            return;
            }
            if( combine==null ) {
            if( pi.HeadDefined )
                // error: multiple heads
                ReportError( ERR_MULTIPLE_HEADS, r.name );
            pi.HeadDefined = true;
            combine = pi.Combine;
            } else {
            pi.Combine = combine;
            }

            if( r.exp==null )
            r.exp = body;
            else {
            if(combine=="interleave")	r.exp = Builder.CreateInterleave( r.exp, body );
            else
            if(combine=="choice")		r.exp = Builder.CreateChoice( r.exp, body );
            else {
                // error: invalid combine value
                ReportError( ERR_INVALID_COMBINE, combine );
            }
            }
        }
 public static Expression Calc( Expression exp, Token token, ExpBuilder builder )
 {
     return exp.Visit( new Residual(token,builder) );
 }
	private Expression VerifyText( Expression exp, Expression[] atoms ) {
		string literal;
		
		if(characters.Length==0) {
			literal = String.Empty;
		} else {
			literal = characters.ToString();
			characters = new StringBuilder();
		}
		bool ignorable = (literal.Trim().Length==0);
		
		
		Trace.WriteLine("characters: "+literal.Trim());
		
		StringToken token = new StringToken(literal,builder,this);
		
		Expression r = Residual.Calc( exp, token, builder );
		if(ignorable)	exp = builder.CreateChoice( exp, r );
		else			exp = r;
		
		if(exp==Expression.NotAllowed) {
			// error: unexpected literal
			if(literal.Length>20)	literal=literal.Substring(0,20)+" ...";
			ReportError( ERR_INVALID_TEXT, literal );
		}
		
		if(atoms!=null)
			for( int i=atoms.Length-1; i>=0; i-- ) {
				r = Residual.Calc( atoms[i], token, builder );
				if(ignorable)	atoms[i] = builder.CreateChoice( atoms[i], r );
				else			atoms[i] = r;
			}
		
		return exp;
	}
	private Expression Verify( Expression contentModel ) {
		return Verify(contentModel,null);
	}
	protected Expression OnAttribute( Expression exp, Expression[] atoms ) {
		if(document.Name!="xmlns"
		&& document.Prefix!="xmlns") {
			Trace.WriteLine("@"+document.Name);
			
			AttributeToken token = new AttributeToken(
					document.NamespaceURI,
					document.LocalName,
					document.Value,
					this, builder );
			AttFeeder feeder = new AttFeeder(builder,token);

			exp = exp.Visit(feeder);
			if( exp==Expression.NotAllowed ) {
				// error: bad attribute
				ReportError(ERR_BAD_ATTRIBUTE,document.Name);
			}
			
			if(atoms!=null)
				for( int i=0; i<atoms.Length; i++ )
					atoms[i] = atoms[i].Visit(feeder);
			
			Trace.WriteLine("residual: " + ExpPrinter.printContentModel(exp));
		}
		return exp;
	}
	private Expression OnElement( Expression contentModel, Expression[] atoms ) {
		contentModel = VerifyText(contentModel,atoms);
		
		Trace.WriteLine("<"+document.Name+">");
		Trace.Indent();
		Trace.WriteLine("expecting: "+ ExpPrinter.printContentModel(contentModel));
		
		ElementExp[] match = ContentModelCollector.Collect(
			contentModel, new XmlName(document.NamespaceURI,document.LocalName) );
		
		if(match[0]==null) {
			// error: unexpected element
			ReportError(ERR_UNEXPECTED_ELEMENT,document.Name);
		}
		
		Expression combinedChild = Expression.NotAllowed;
		int i;
		for( i=0; match[i]!=null; i++ )
			combinedChild = builder.CreateChoice( combinedChild, match[i].exp );
		int clen = i;
		
		Expression[] cp = null;
		if(clen>1) {
			Trace.WriteLine(string.Format("{0} elements are matched",clen));
			cp = new Expression[clen];
			for( i=0; i<clen; i++ )
				cp[i] = match[i].exp;
		}

		Trace.WriteLine("combined child: "+
			ExpPrinter.printContentModel(combinedChild));

		if(document.MoveToFirstAttribute())
			do {
				combinedChild = OnAttribute( combinedChild, cp );
			} while( document.MoveToNextAttribute() );
		
		document.MoveToElement();
		
		combinedChild = attPruner.prune(combinedChild);
		if(combinedChild==Expression.NotAllowed) {
			// error: required attribute is missing
			// TODO: name of required attributes
			ReportError(ERR_MISSING_ATTRIBUTE);
		}
			
		if( !document.IsEmptyElement ) {
			document.ReadStartElement();
			combinedChild = Verify(combinedChild,cp);
			combinedChild = VerifyText(combinedChild,cp);
			Trace.Unindent();
			Trace.WriteLine("</"+document.Name+">");
		} else {
			// treat it as ""
			combinedChild = VerifyText(combinedChild,cp);
			Trace.Unindent();
			Trace.WriteLine("</"+document.Name+">");
		}
		
		if( !combinedChild.IsNullable ) {
			// error: unexpected end of element.
			ReportError( ERR_CONTENTMODEL_INCOMPLETE, document.Name );
		}
		
		document.Read();	// read the end tag.
		
		
		if(cp!=null)
			for( i=0; i<clen; i++ )
				if(!cp[i].IsNullable)
					match[i]=null;
		
		ElementToken e = new ElementToken(match,clen);
		if(atoms!=null)
			for( i=0; i<atoms.Length; i++ )
				atoms[i] = Residual.Calc(atoms[i],e,builder);
		
		contentModel = Residual.Calc(contentModel,e,builder);
		Trace.WriteLine("residual: " + ExpPrinter.printContentModel(contentModel));
		return contentModel;
	}
 public static string printFragment( Expression exp )
 {
     return print(exp,-1,false);
 }
 public static string printContentModel( Expression exp )
 {
     return print(exp,0,true);
 }
        protected void Visit( Expression e )
        {
            bool isComplex = false;
            if( e is BinaryExp )
            isComplex = true;
            if( e is ReferenceExp )
            isComplex = true;

            if(isComplex)	writer.Write('(');
            e.Visit(this);
            if(isComplex)	writer.Write(')');
        }
 protected void OptimizedChoice( Expression exp )
 {
     if( exp is OneOrMoreExp ) {
     Visit( ((OneOrMoreExp)exp).exp );
     writer.Write('*');
     return;
     } else {
     Visit(exp);
     writer.Write('?');
     }
 }