// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
//
-// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
//
using System;
using System.Collections;
-using System.ComponentModel;
-using System.Drawing;
-using System.Diagnostics;
+using System.CodeDom.Compiler;
using System.IO;
-using System.Reflection;
using System.Text;
-using System.Text.RegularExpressions;
+using System.Web.Caching;
using System.Web.UI;
-using System.Web.UI.HtmlControls;
-using System.Web.UI.WebControls;
using System.Web.Util;
namespace System.Web.Compilation
{
-
-class ControlStack
-{
- private Stack controls;
- private ControlStackData top;
- private bool space_between_tags;
- private bool sbt_valid;
-
- class ControlStackData
+ class BuilderLocation
{
- public Type controlType;
- public string controlID;
- public string tagID;
- public ChildrenKind childKind;
- public string defaultPropertyName;
- public int childrenNumber;
- public Type container;
- public StringBuilder dataBindFunction;
- public StringBuilder codeRenderFunction;
- public bool useCodeRender;
- public int codeRenderIndex;
-
- public ControlStackData (Type controlType,
- string controlID,
- string tagID,
- ChildrenKind childKind,
- string defaultPropertyName,
- Type container)
- {
- this.controlType = controlType;
- this.controlID = controlID;
- this.tagID = tagID;
- this.childKind = childKind;
- this.defaultPropertyName = defaultPropertyName;
- this.container = container;
- childrenNumber = 0;
- }
+ public ControlBuilder Builder;
+ public ILocation Location;
- public override string ToString ()
+ public BuilderLocation (ControlBuilder builder, ILocation location)
{
- return controlType + " " + controlID + " " + tagID + " " + childKind + " " + childrenNumber;
+ this.Builder = builder;
+ this.Location = location;
}
}
- public ControlStack ()
+ class BuilderLocationStack : Stack
{
- controls = new Stack ();
- }
+ public override void Push (object o)
+ {
+ if (!(o is BuilderLocation))
+ throw new InvalidOperationException ();
- private Type GetContainerType (Type type)
- {
- if (type != typeof (System.Web.UI.Control) &&
- !type.IsSubclassOf (typeof (System.Web.UI.Control)))
- return null;
+ base.Push (o);
+ }
- Type container_type;
- if (type == typeof (System.Web.UI.WebControls.DataList))
- container_type = typeof (System.Web.UI.WebControls.DataListItem);
- else if (type == typeof (System.Web.UI.WebControls.DataGrid))
- container_type = typeof (System.Web.UI.WebControls.DataGridItem);
- else if (type == typeof (System.Web.UI.WebControls.Repeater))
- container_type = typeof (System.Web.UI.WebControls.RepeaterItem);
- else if (type == typeof (ListControl) || type.IsSubclassOf (typeof (ListControl)))
- container_type = type;
- else
- container_type = Container;
-
- return container_type;
- }
-
- public void Push (object o)
- {
- if (!(o is ControlStackData))
- return;
-
- controls.Push (o);
- top = (ControlStackData) o;
- sbt_valid = false;
- }
-
- public void Push (Type controlType,
- string controlID,
- string tagID,
- ChildrenKind childKind,
- string defaultPropertyName)
- {
- Type container_type = null;
- if (controlType != null){
- AddChild ();
- container_type = GetContainerType (controlType);
- if (container_type == null)
- container_type = this.Container;
+ public virtual void Push (ControlBuilder builder, ILocation location)
+ {
+ BuilderLocation bl = new BuilderLocation (builder, location);
+ Push (bl);
}
- top = new ControlStackData (controlType,
- controlID,
- tagID,
- childKind,
- defaultPropertyName,
- container_type);
- sbt_valid = false;
- controls.Push (top);
- }
-
- public object Pop ()
- {
- object item = controls.Pop ();
- if (controls.Count != 0)
- top = (ControlStackData) controls.Peek ();
- sbt_valid = false;
- return item;
- }
-
- public Type PeekType ()
- {
- return top.controlType;
- }
-
- public string PeekControlID ()
- {
- return top.controlID;
- }
-
- public string PeekTagID ()
- {
- return top.tagID;
- }
-
- public ChildrenKind PeekChildKind ()
- {
- return top.childKind;
- }
-
- public string PeekDefaultPropertyName ()
- {
- return top.defaultPropertyName;
- }
-
- public void AddChild ()
- {
- if (top != null)
- top.childrenNumber++;
- }
-
- public bool HasDataBindFunction ()
- {
- if (top.dataBindFunction == null || top.dataBindFunction.Length == 0)
- return false;
- return true;
- }
-
- public bool UseCodeRender
- {
- get {
- if (top.codeRenderFunction == null || top.codeRenderFunction.Length == 0)
- return false;
- return top.useCodeRender;
+ public new BuilderLocation Peek ()
+ {
+ return (BuilderLocation) base.Peek ();
}
- set { top.useCodeRender= value; }
- }
-
- public bool SpaceBetweenTags
- {
- get {
- if (!sbt_valid){
- sbt_valid = true;
- Type type = top.controlType;
- if (type.Namespace == "System.Web.UI.WebControls")
- space_between_tags = true;
- else if (type.IsSubclassOf (typeof (System.Web.UI.WebControls.WebControl)))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlSelect))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlTable))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableRow))
- space_between_tags = true;
- else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableCell))
- space_between_tags = true;
- else
- space_between_tags = false;
- }
- return space_between_tags;
- }
- }
-
- public Type Container {
- get {
- if (top == null)
- return null;
-
- return top.container;
- }
- }
-
- public StringBuilder DataBindFunction
- {
- get {
- if (top.dataBindFunction == null)
- top.dataBindFunction = new StringBuilder ();
- return top.dataBindFunction;
+ public new BuilderLocation Pop ()
+ {
+ return (BuilderLocation) base.Pop ();
}
- }
- public int CodeRenderIndex {
- get {
- return top.codeRenderIndex++;
- }
- }
-
- public StringBuilder CodeRenderFunction
- {
- get {
- if (top.codeRenderFunction == null)
- top.codeRenderFunction = new StringBuilder ();
- return top.codeRenderFunction;
+ public ControlBuilder Builder {
+ get { return Peek ().Builder; }
}
}
- public int ChildIndex
+ class ParserStack
{
- get { return top.childrenNumber - 1; }
- }
-
- public int Count
- {
- get { return controls.Count; }
- }
+ Hashtable files;
+ Stack parsers;
+ AspParser current;
- public override string ToString ()
- {
- return top.ToString () + " " + top.useCodeRender;
- }
-
-}
-
-class ArrayListWrapper
-{
- private ArrayList list;
- private int index;
-
- public ArrayListWrapper (ArrayList list)
- {
- this.list = list;
- index = -1;
- }
-
- private void CheckIndex ()
- {
- if (index == -1 || index == list.Count)
- throw new InvalidOperationException ();
- }
-
- public object Current
- {
- get {
- CheckIndex ();
- return list [index];
- }
-
- set {
- CheckIndex ();
- list [index] = value;
+ public ParserStack ()
+ {
+ files = new Hashtable (); // may be this should be case sensitive for windows
+ parsers = new Stack ();
}
- }
-
- public bool MoveNext ()
- {
- if (index < list.Count)
- index++;
-
- return index < list.Count;
- }
-}
-
-class AspGenerator
-{
- private object [] parts;
- private ArrayListWrapper elements;
- private StringBuilder prolog;
- private StringBuilder declarations;
- private StringBuilder script;
- private StringBuilder constructor;
- private StringBuilder init_funcs;
- private StringBuilder epilog;
- private StringBuilder current_function;
- private Stack functions;
- private ControlStack controls;
- private bool parse_ok;
- private bool has_form_tag;
- private AspComponentFoundry aspFoundry;
-
- private string classDecl;
- private string className;
- private string interfaces;
- private string basetype;
- private string parent;
- private Type parentType;
- private string fullPath;
-
- Hashtable options;
- string privateBinPath;
- string main_directive;
- static string app_file_wrong = "The content in the application file is not valid.";
-
- bool isPage;
- bool isUserControl;
- bool isApplication;
-
- HttpContext context;
-
- SessionState sessionState = SessionState.Enabled;
-
- static Type styleType = typeof (System.Web.UI.WebControls.Style);
- static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
-
- enum UserControlResult
- {
- OK = 0,
- FileNotFound = 1,
- CompilationFailed = 2
- }
-
- enum SessionState
- {
- Enabled,
- ReadOnly,
- Disabled
- }
-
- public AspGenerator (string pathToFile, ArrayList elements)
- {
- if (elements == null)
- throw new ArgumentNullException ();
-
- this.elements = new ArrayListWrapper (elements);
- string filename = Path.GetFileName (pathToFile);
- this.className = filename.Replace ('.', '_'); // Overridden by @ Page classname
- this.className = className.Replace ('-', '_');
- this.className = className.Replace (' ', '_');
- Options ["ClassName"] = this.className;
- this.fullPath = Path.GetFullPath (pathToFile);
-
- this.has_form_tag = false;
- AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
- privateBinPath = setup.PrivateBinPath;
- // This is a hack until we can run stuff in different domains
- if (privateBinPath == null || privateBinPath.Length == 0)
- privateBinPath = "bin";
-
- if (!Path.IsPathRooted (privateBinPath))
- privateBinPath = Path.Combine (setup.ApplicationBase, privateBinPath);
- Init ();
- }
-
- public string BaseType {
- get { return basetype; }
-
- set {
- if (parent == null)
- parent = value;
-
- basetype = value;
- isUserControl = (basetype == "System.Web.UI.UserControl");
- isPage = (basetype == "System.Web.UI.Page");
- isApplication = (basetype == "System.Web.HttpApplication");
- }
- }
-
- public bool IsUserControl {
- get { return isUserControl; }
- }
-
- public bool IsPage {
- get { return isPage; }
- }
-
- public bool IsApplication {
- get { return isApplication; }
- }
-
- public string Interfaces {
- get { return interfaces; }
- }
-
- public Hashtable Options {
- get {
- if (options == null)
- options = new Hashtable ();
+ public bool Push (AspParser parser)
+ {
+ if (files.Contains (parser.Filename))
+ return false;
- return options;
- }
- }
-
- internal HttpContext Context {
- get { return context; }
- set { context = value; }
- }
-
- bool AddUsing (string nspace)
- {
- string _using = "using " + nspace + ";";
- if (prolog.ToString ().IndexOf (_using) == -1) {
- prolog.AppendFormat ("\t{0}\n", _using);
+ files [parser.Filename] = true;
+ parsers.Push (parser);
+ current = parser;
return true;
}
- return false;
- }
-
- void AddInterface (Type type)
- {
- AddInterface (type.ToString ());
- }
-
- public void AddInterface (string iface)
- {
- if (interfaces == null) {
- interfaces = ", " + iface;
- } else {
- string s = ", " + iface;
- if (interfaces.IndexOf (s) == -1)
- interfaces += s;
- }
- }
+ public AspParser Pop ()
+ {
+ if (parsers.Count == 0)
+ return null;
- private AspComponentFoundry Foundry
- {
- get {
- if (aspFoundry == null)
- aspFoundry = new AspComponentFoundry ();
+ files.Remove (current.Filename);
+ AspParser result = (AspParser) parsers.Pop ();
+ if (parsers.Count > 0)
+ current = (AspParser) parsers.Peek ();
+ else
+ current = null;
- return aspFoundry;
+ return result;
}
- }
-
- private void Init ()
- {
- controls = new ControlStack ();
- controls.Push (typeof (System.Web.UI.Control), "Root", null, ChildrenKind.CONTROLS, null);
- prolog = new StringBuilder ();
- declarations = new StringBuilder ();
- script = new StringBuilder ();
- constructor = new StringBuilder ();
- init_funcs = new StringBuilder ();
- epilog = new StringBuilder ();
-
- current_function = new StringBuilder ();
- functions = new Stack ();
- functions.Push (current_function);
-
- parts = new Object [6];
- parts [0] = prolog;
- parts [1] = declarations;
- parts [2] = script;
- parts [3] = constructor;
- parts [4] = init_funcs;
- parts [5] = epilog;
-
- prolog.Append ("namespace ASP {\n" +
- "\tusing System;\n" +
- "\tusing System.Collections;\n" +
- "\tusing System.Collections.Specialized;\n" +
- "\tusing System.Configuration;\n" +
- "\tusing System.IO;\n" +
- "\tusing System.Text;\n" +
- "\tusing System.Text.RegularExpressions;\n" +
- "\tusing System.Web;\n" +
- "\tusing System.Web.Caching;\n" +
- "\tusing System.Web.Security;\n" +
- "\tusing System.Web.SessionState;\n" +
- "\tusing System.Web.UI;\n" +
- "\tusing System.Web.UI.WebControls;\n" +
- "\tusing System.Web.UI.HtmlControls;\n");
-
- declarations.Append ("\t\tprivate static int __autoHandlers;\n");
-
- current_function.Append ("\t\tprivate void __BuildControlTree (System.Web.UI.Control __ctrl)\n\t\t{\n");
- if (!IsUserControl)
- current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
- "(System.Web.UI.IParserAccessor) __ctrl;\n\n");
- else
- controls.UseCodeRender = true;
- }
-
- public StringReader GetCode ()
- {
- if (!parse_ok)
- throw new ApplicationException ("You gotta call ProcessElements () first!");
-
- StringBuilder code = new StringBuilder ();
- for (int i = 0; i < parts.Length; i++)
- code.Append ((StringBuilder) parts [i]);
-
- return new StringReader (code.ToString ());
- }
-
- public void Print ()
- {
- if (!parse_ok){
- Console.WriteLine ("//Warning!!!: Elements not correctly parsed.");
+
+ public AspParser Parser {
+ get { return current; }
}
- Console.Write (GetCode ().ReadToEnd ());
- }
-
- // Regex.Escape () make some illegal escape sequences for a C# source.
- private string Escape (string input)
- {
- if (input == null)
- return String.Empty;
-
- string output = input.Replace ("\\", "\\\\");
- output = output.Replace ("\"", "\\\"");
- output = output.Replace ("\t", "\\t");
- output = output.Replace ("\r", "\\r");
- output = output.Replace ("\n", "\\n");
- output = output.Replace ("\n", "\\n");
- return output;
+ public string Filename {
+ get { return current.Filename; }
+ }
}
- bool AddProtectedField (Type type, string fieldName)
- {
- if (parentType == null) {
- declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
- return true;
- }
-
- FieldInfo field = parentType.GetField (fieldName, BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.Static);
-
- if (field == null || (!field.IsPublic && !field.IsFamily)) {
- declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
- return true;
+ class AspGenerator
+ {
+ ParserStack pstack;
+ BuilderLocationStack stack;
+ TemplateParser tparser;
+ StringBuilder text;
+ RootBuilder rootBuilder;
+ bool inScript, javascript;
+ ILocation location;
+ static Hashtable emptyHash = new Hashtable ();
+
+ public AspGenerator (TemplateParser tparser)
+ {
+ this.tparser = tparser;
+ tparser.AddDependency (tparser.InputFile);
+ text = new StringBuilder ();
+ stack = new BuilderLocationStack ();
+ rootBuilder = new RootBuilder (tparser);
+ stack.Push (rootBuilder, null);
+ tparser.RootBuilder = rootBuilder;
+ pstack = new ParserStack ();
}
- if (!field.FieldType.IsAssignableFrom (type)) {
- string message = String.Format ("The base class includes the field '{0}', but its " +
- "type '{1}' is not compatible with {2}",
- fieldName, field.FieldType, type);
-
- throw new ApplicationException (message);
+ public AspParser Parser {
+ get { return pstack.Parser; }
}
-
- return false;
- }
-
- private Type LoadParentType (string typeName)
- {
- // First try loaded assemblies, then try assemblies in Bin directory.
- // By now i do this 'by hand' but may be this is a runtime/gac task.
- Type type = Type.GetType (typeName);
- if (type != null)
- return type;
-
- string [] binDlls = Directory.GetFiles (privateBinPath, "*.dll");
- Assembly assembly;
- foreach (string dll in binDlls) {
- string dllPath = Path.Combine (privateBinPath, dll);
- assembly = null;
- try {
- assembly = Assembly.LoadFrom (dllPath);
- type = assembly.GetType (typeName);
- } catch (Exception e) {
- if (assembly != null) {
- Console.WriteLine ("ASP.NET Warning: assembly {0} loaded", dllPath);
- Console.WriteLine ("ASP.NET Warning: but type {0} not found", typeName);
- } else {
- Console.WriteLine ("ASP.NET Warning: unable to load type {0} from {1}",
- typeName, dllPath);
- }
- Console.WriteLine ("ASP.NET Warning: error was: {0}", e.Message);
- }
-
- if (type != null)
- return type;
+
+ public string Filename {
+ get { return pstack.Filename; }
}
+
+ BaseCompiler GetCompilerFromType ()
+ {
+ Type type = tparser.GetType ();
+ if (type == typeof (PageParser))
+ return new PageCompiler ((PageParser) tparser);
- return null;
- }
+ if (type == typeof (ApplicationFileParser))
+ return new GlobalAsaxCompiler ((ApplicationFileParser) tparser);
- private void PageDirective (TagAttributes att)
- {
- if (att ["ClassName"] != null){
- this.className = (string) att ["ClassName"];
- Options ["ClassName"] = className;
- }
+ if (type == typeof (UserControlParser))
+ return new UserControlCompiler ((UserControlParser) tparser);
- if (att ["EnableSessionState"] != null){
- if (!IsPage)
- throw new ApplicationException ("EnableSessionState not allowed here.");
-
- string est = (string) att ["EnableSessionState"];
- if (0 == String.Compare (est, "false", true))
- sessionState = SessionState.Disabled;
- else if (0 == String.Compare (est, "true", true))
- sessionState = SessionState.Enabled;
- else if (0 == String.Compare (est, "readonly", true))
- sessionState = SessionState.ReadOnly;
- else
- throw new ApplicationException ("EnableSessionState in Page directive not set to " +
- "a correct value: " + est);
+ throw new Exception ("Got type: " + type);
}
+
+ void InitParser (string filename)
+ {
+ StreamReader reader = new StreamReader (filename, WebEncoding.FileEncoding);
+ AspParser parser = new AspParser (filename, reader);
+ reader.Close ();
+ parser.Error += new ParseErrorHandler (ParseError);
+ parser.TagParsed += new TagParsedHandler (TagParsed);
+ parser.TextParsed += new TextParsedHandler (TextParsed);
+ if (!pstack.Push (parser))
+ throw new ParseException (Location, "Infinite recursion detected including file: " + filename);
+ tparser.AddDependency (filename);
+ }
+
+ void DoParse ()
+ {
+ pstack.Parser.Parse ();
+ if (text.Length > 0)
+ FlushText ();
- if (att ["Inherits"] != null) {
- parent = (string) att ["Inherits"];
- parentType = LoadParentType (parent);
- if (parentType == null)
- throw new ApplicationException ("The class " + parent + " cannot be found.");
+ pstack.Pop ();
}
- if (att ["CompilerOptions"] != null)
- Options ["CompilerOptions"] = (string) att ["CompilerOptions"];
-
- if (att ["AutoEventWireup"] != null) {
- if (options ["AutoEventWireup"] != null)
- throw new ApplicationException ("Already have an AutoEventWireup attribute");
-
- bool autoevent = true;
- string v = att ["AutoEventWireup"] as string;
- try {
- autoevent = Convert.ToBoolean (v);
- } catch (Exception) {
- throw new ApplicationException ("'" + v + "' is not a valid value for AutoEventWireup");
+ public Type GetCompiledType ()
+ {
+ Type type = (Type) HttpRuntime.Cache.Get (tparser.InputFile);
+ if (type != null) {
+ return type;
}
- options ["AutoEventWireup"] = autoevent;
- }
- //FIXME: add support for more attributes.
- }
+ InitParser (Path.GetFullPath (tparser.InputFile));
+ DoParse ();
+#if DEBUG
+ PrintTree (rootBuilder, 0);
+#endif
- void AddReference (string dll)
- {
- string references = Options ["References"] as string;
- if (references == null)
- references = dll;
- else
- references = references + " " + dll;
+ if (stack.Count > 1)
+ throw new ParseException (stack.Builder.location,
+ "Expecting </" + stack.Builder.TagName + ">" + stack.Builder);
- Options ["References"] = references;
- }
+ BaseCompiler compiler = GetCompilerFromType ();
- private void RegisterDirective (TagAttributes att)
- {
- string tag_prefix = (string) (att ["tagprefix"] == null ? "" : att ["tagprefix"]);
- string name_space = (string) (att ["namespace"] == null ? "" : att ["namespace"]);
- string assembly_name = (string) (att ["assembly"] == null ? "" : att ["assembly"]);
- string tag_name = (string) (att ["tagname"] == null ? "" : att ["tagname"]);
- string src = (string) (att ["src"] == null ? "" : att ["src"]);
-
- if (tag_prefix != "" && name_space != "" && assembly_name != ""){
- if (tag_name != "" || src != "")
- throw new ApplicationException ("Invalid attributes for @ Register: " +
- att.ToString ());
-
- AddUsing (name_space);
- string dll = privateBinPath + Path.DirectorySeparatorChar + assembly_name + ".dll";
- // Hack: it should use assembly.load semantics...
- // may be when we don't run mcs as a external program...
- if (!File.Exists (dll))
- dll = assembly_name;
-
- Foundry.RegisterFoundry (tag_prefix, dll, name_space);
- AddReference (dll);
- return;
- }
+ type = compiler.GetCompiledType ();
+ CacheDependency cd = new CacheDependency ((string[])
+ tparser.Dependencies.ToArray (typeof (string)));
- if (tag_prefix != "" && tag_name != "" && src != ""){
- if (name_space != "" && assembly_name != "")
- throw new ApplicationException ("Invalid attributes for @ Register: " +
- att.ToString ());
-
- if (!src.EndsWith (".ascx"))
- throw new ApplicationException ("Source file extension for controls " +
- "must be .ascx");
-
- UserControlData data = GenerateUserControl (src, Context);
- switch (data.result) {
- case UserControlResult.OK:
- AddUsing ("ASP");
- string dll = "output" + Path.DirectorySeparatorChar + data.assemblyName + ".dll";
- Foundry.RegisterFoundry (tag_prefix, tag_name, data.assemblyName, "ASP", data.className);
- AddReference (data.assemblyName);
- break;
- case UserControlResult.FileNotFound:
- throw new ApplicationException ("File '" + src + "' not found.");
- case UserControlResult.CompilationFailed:
- //TODO: should say where the generated .cs file is for the server to
- //show the source and the compiler error
- throw new NotImplementedException ();
- }
- return;
+ HttpRuntime.Cache.Insert (tparser.InputFile, type, cd);
+ return type;
}
- throw new ApplicationException ("Invalid combination of attributes in " +
- "@ Register: " + att.ToString ());
- }
+#if DEBUG
+ static void PrintTree (ControlBuilder builder, int indent)
+ {
+ if (builder == null)
+ return;
- private void ProcessDirective ()
- {
- Directive directive = (Directive) elements.Current;
- TagAttributes att = directive.Attributes;
- if (att == null)
- return;
-
- string value;
- string id = directive.TagID.ToUpper ();
- switch (id){
- case "APPLICATION":
- if (main_directive != null)
- throw new ApplicationException (id + " not allowed after " + main_directive);
-
- if (!IsApplication)
- throw new ApplicationException ("@Application not allowed.");
-
- string inherits = att ["inherits"] as string;
- if (inherits != null)
- Options ["Inherits"] = inherits;
-
- main_directive = directive.TagID;
- break;
- case "PAGE":
- case "CONTROL":
- if (main_directive != null)
- throw new ApplicationException (id + " not allowed after " + main_directive);
-
- if (IsUserControl && id != "CONTROL")
- throw new ApplicationException ("@Page not allowed for user controls.");
- else if (IsPage && id != "PAGE")
- throw new ApplicationException ("@Control not allowed here. This is a page!");
-
- PageDirective (att);
- main_directive = directive.TagID;
- break;
- case "IMPORT":
- value = att ["namespace"] as string;
- if (value == null || att.Count > 1)
- throw new ApplicationException ("Wrong syntax in Import directive.");
-
- string _using = "using " + value + ";";
- if (AddUsing (value) == true) {
- string imports = Options ["Import"] as string;
- if (imports == null) {
- imports = value;
- } else {
- imports += "," + value;
- }
+ string i = new string ('\t', indent);
+ Console.Write (i);
+ Console.WriteLine ("b: {0} id: {1} type: {2} parent: {3}",
+ builder, builder.ID, builder.ControlType, builder.parentBuilder);
- Options ["Import"] = imports;
- }
- break;
- case "IMPLEMENTS":
- if (IsApplication)
- throw new ApplicationException ("@ Implements not allowed in an application file.");
-
- string iface = (string) att ["interface"];
- AddInterface (iface);
- break;
- case "REGISTER":
- if (IsApplication)
- throw new ApplicationException ("@ Register not allowed in an application file.");
-
- RegisterDirective (att);
- break;
- case "ASSEMBLY":
- if (att.Count > 1)
- throw new ApplicationException ("Wrong syntax in Assembly directive.");
-
- string name = att ["name"] as string;
- string src = att ["src"] as string;
-
- if (name == null && src == null)
- throw new ApplicationException ("Wrong syntax in Assembly directive.");
-
- if (IsApplication && src != null)
- throw new ApplicationException ("'name' attribute expected.");
-
- value = (name == null) ? src : name;
- string assemblies = Options ["Assembly"] as string;
- if (assemblies == null) {
- assemblies = value;
- } else {
- assemblies += "," + value;
+ if (builder.Children != null)
+ foreach (object o in builder.Children) {
+ if (o is ControlBuilder)
+ PrintTree ((ControlBuilder) o, indent++);
}
-
- Options ["Assembly"] = assemblies;
- break;
}
- }
-
- private void ProcessPlainText ()
- {
- PlainText asis = (PlainText) elements.Current;
- string trimmed = asis.Text.Trim ();
- if (trimmed == String.Empty && controls.SpaceBetweenTags == true)
- return;
-
- if (IsApplication) {
- if (trimmed != String.Empty)
- throw new ApplicationException (app_file_wrong);
- return;
+#endif
+
+ static void PrintLocation (ILocation loc)
+ {
+ Console.WriteLine ("\tFile name: " + loc.Filename);
+ Console.WriteLine ("\tBegin line: " + loc.BeginLine);
+ Console.WriteLine ("\tEnd line: " + loc.EndLine);
+ Console.WriteLine ("\tBegin column: " + loc.BeginColumn);
+ Console.WriteLine ("\tEnd column: " + loc.EndColumn);
+ Console.WriteLine ("\tPlainText: " + loc.PlainText);
+ Console.WriteLine ();
}
- if (trimmed != String.Empty && controls.PeekChildKind () != ChildrenKind.CONTROLS){
- string tag_id = controls.PeekTagID ();
- throw new ApplicationException ("Literal content not allowed for " + tag_id);
+ void ParseError (ILocation location, string message)
+ {
+ throw new ParseException (location, message);
}
-
- string escaped_text = Escape (asis.Text);
- current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject (" +
- "new System.Web.UI.LiteralControl (\"{0}\"));\n",
- escaped_text);
- StringBuilder codeRenderFunction = controls.CodeRenderFunction;
- codeRenderFunction.AppendFormat ("\t\t\t__output.Write (\"{0}\");\n", escaped_text);
- }
- private string EnumValueNameToString (Type enum_type, string value_name)
- {
- if (value_name.EndsWith ("*"))
- throw new ApplicationException ("Invalid property value: '" + value_name +
- ". It must be a valid " + enum_type.ToString () + " value.");
-
- MemberInfo [] nested_types = enum_type.FindMembers (MemberTypes.Field,
- BindingFlags.Public | BindingFlags.Static,
- Type.FilterNameIgnoreCase,
- value_name);
-
- if (nested_types.Length == 0)
- throw new ApplicationException ("Value " + value_name + " not found in enumeration " +
- enum_type.ToString ());
- if (nested_types.Length > 1)
- throw new ApplicationException ("Value " + value_name + " found " +
- nested_types.Length + " in enumeration " +
- enum_type.ToString ());
-
- return enum_type.ToString () + "." + nested_types [0].Name;
- }
-
- private void NewControlFunction (string tag_id,
- string control_id,
- Type control_type,
- ChildrenKind children_kind,
- string defaultPropertyName)
- {
- ChildrenKind prev_children_kind = controls.PeekChildKind ();
- if (prev_children_kind == ChildrenKind.NONE ||
- prev_children_kind == ChildrenKind.PROPERTIES){
- string prev_tag_id = controls.PeekTagID ();
- throw new ApplicationException ("Child controls not allowed for " + prev_tag_id);
- }
+ void TagParsed (ILocation location, TagType tagtype, string tagid, TagAttributes attributes)
+ {
+ this.location = new Location (location);
+ if (tparser != null)
+ tparser.Location = location;
- if (prev_children_kind == ChildrenKind.DBCOLUMNS &&
- control_type != typeof (System.Web.UI.WebControls.DataGridColumn) &&
- !control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
- throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
- "System.Web.UI.WebControls.DataGridColum " +
- "objects are allowed");
- else if (prev_children_kind == ChildrenKind.LISTITEM &&
- control_type != typeof (System.Web.UI.WebControls.ListItem))
- throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
- "System.Web.UI.WebControls.ListItem " +
- "objects are allowed");
- else if (prev_children_kind == ChildrenKind.HTMLROW &&
- control_type != typeof (System.Web.UI.HtmlControls.HtmlTableRow))
- throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
- "System.Web.UI.HtmlControls.HtmlTableRow " +
- "objects are allowed");
- else if (prev_children_kind == ChildrenKind.HTMLCELL &&
- control_type != typeof (System.Web.UI.HtmlControls.HtmlTableCell))
- throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
- "System.Web.UI.HtmlControls.HtmlTableCell " +
- "objects are allowed");
-
-
- StringBuilder func_code = new StringBuilder ();
- current_function = func_code;
- if (0 == String.Compare (tag_id, "form", true)){
- if (has_form_tag)
- throw new ApplicationException ("Only one form server tag allowed.");
- has_form_tag = true;
- }
+ if (text.Length != 0)
+ FlushText ();
- controls.Push (control_type, control_id, tag_id, children_kind, defaultPropertyName);
- bool is_generic = control_type == typeof (System.Web.UI.HtmlControls.HtmlGenericControl);
- functions.Push (current_function);
- if (control_type != typeof (System.Web.UI.WebControls.ListItem) &&
- prev_children_kind != ChildrenKind.DBCOLUMNS) {
- current_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_" +
- "{0} ()\n\t\t{{\n\t\t\t{1} __ctrl;\n\n\t\t\t__ctrl" +
- " = new {1} ({2});\n\t\t\tthis.{0} = __ctrl;\n",
- control_id, control_type,
- (is_generic? "\"" + tag_id + "\"" : ""));
- } else {
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ()\n\t\t{{" +
- "\n\t\t\t{1} __ctrl;\n\t\t\t__ctrl = new {1} ();" +
- "\n\t\t\tthis.{0} = __ctrl;\n",
- control_id, control_type);
- }
+ if (0 == String.Compare (tagid, "script", true)) {
+ if (ProcessScript (tagtype, attributes))
+ return;
+ }
- if (children_kind == ChildrenKind.CONTROLS || children_kind == ChildrenKind.OPTION)
- current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
- "(System.Web.UI.IParserAccessor) __ctrl;\n");
- }
-
- private void DataBoundProperty (Type target, string varName, string value)
- {
- if (value == "")
- throw new ApplicationException ("Empty data binding tag.");
-
- string control_id = controls.PeekControlID ();
- string control_type_string = controls.PeekType ().ToString ();
- StringBuilder db_function = controls.DataBindFunction;
- string container;
- if (controls.Container == null)
- container = "System.Web.UI.Control";
- else
- container = controls.Container.ToString ();
-
- if (db_function.Length == 0)
- db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
- "System.EventArgs e) {{\n" +
- "\t\t\t{1} Container;\n" +
- "\t\t\t{2} target;\n" +
- "\t\t\ttarget = ({2}) sender;\n" +
- "\t\t\tContainer = ({1}) target.BindingContainer;\n",
- control_id, container, control_type_string);
-
- /* Removes '<%#' and '%>' */
- string real_value = value.Remove (0,3);
- real_value = real_value.Remove (real_value.Length - 2, 2);
- real_value = real_value.Trim ();
-
- if (target == typeof (string))
- db_function.AppendFormat ("\t\t\ttarget.{0} = System.Convert.ToString ({1});\n",
- varName, real_value);
- else
- db_function.AppendFormat ("\t\t\ttarget.{0} = ({1}) ({2});\n",
- varName, target, real_value);
- }
+ switch (tagtype) {
+ case TagType.Directive:
+ if (tagid == "")
+ tagid = tparser.DefaultDirectiveName;
- /*
- * Returns true if it generates some code for the specified property
- */
- private void AddCodeForPropertyOrField (Type type, string var_name, string att, bool isDataBound)
- {
- /* FIXME: should i check for this or let the compiler fail?
- * if (!prop.CanWrite)
- * ....
- */
- if (isDataBound) {
- DataBoundProperty (type, var_name, att);
- }
- else if (type == typeof (string)){
- if (att == null)
- throw new ApplicationException ("null value for attribute " + var_name );
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = \"{1}\";\n", var_name,
- Escape (att)); // FIXME: really Escape this?
- }
- else if (type.IsEnum){
- if (att == null)
- throw new ApplicationException ("null value for attribute " + var_name );
-
- string enum_value = EnumValueNameToString (type, att);
-
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, enum_value);
- }
- else if (type == typeof (bool)){
- string value;
- if (att == null)
- value = "true"; //FIXME: is this ok for non Style properties?
- else if (0 == String.Compare (att, "true", true))
- value = "true";
- else if (0 == String.Compare (att, "false", true))
- value = "false";
- else
- throw new ApplicationException ("Value '" + att + "' is not a valid boolean.");
+ tparser.AddDirective (tagid, attributes.GetDictionary (null));
+ break;
+ case TagType.Tag:
+ if (!ProcessTag (tagid, attributes))
+ TextParsed (location, location.PlainText);
+ break;
+ case TagType.Close:
+ if (!CloseControl (tagid))
+ TextParsed (location, location.PlainText);
+ break;
+ case TagType.SelfClosing:
+ int count = stack.Count;
+ if (!ProcessTag (tagid, attributes)) {
+ TextParsed (location, location.PlainText);
+ } else if (stack.Count != count) {
+ CloseControl (tagid);
+ }
+ break;
+ case TagType.DataBinding:
+ goto case TagType.CodeRender;
+ case TagType.CodeRenderExpression:
+ goto case TagType.CodeRender;
+ case TagType.CodeRender:
+ ProcessCode (tagtype, tagid, location);
+ break;
+ case TagType.Include:
+ string file = attributes ["virtual"] as string;
+ bool isvirtual = (file != null);
+ if (!isvirtual)
+ file = attributes ["file"] as string;
+
+ if (isvirtual) {
+ file = tparser.MapPath (file);
+ } else if (!Path.IsPathRooted (file)) {
+ file = UrlUtils.Combine (tparser.BaseVirtualDir, file);
+ }
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (System.Web.UI.WebControls.Unit)){
- //FIXME: should use the culture specified in Page
- try {
- Unit value = Unit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
- } catch (Exception) {
- throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
- }
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
- "System.Web.UI.WebControls.Unit.Parse (\"{1}\", " +
- "System.Globalization.CultureInfo.InvariantCulture);\n",
- var_name, att);
- }
- else if (type == typeof (System.Web.UI.WebControls.FontUnit)){
- //FIXME: should use the culture specified in Page
- try {
- FontUnit value = FontUnit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
- } catch (Exception) {
- throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
+ InitParser (file);
+ DoParse ();
+ break;
+ default:
+ break;
}
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
- "System.Web.UI.WebControls.FontUnit.Parse (\"{1}\", " +
- "System.Globalization.CultureInfo.InvariantCulture);\n",
- var_name, att);
+ //PrintLocation (location);
}
- else if (type == typeof (Int16) || type == typeof (Int32) || type == typeof (Int64)) {
- long value;
- try {
- value = Int64.Parse (att); //FIXME: should use the culture specified in Page
- } catch (Exception){
- throw new ApplicationException (att + " is not a valid signed number " +
- "or is out of range.");
- }
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (UInt16) || type == typeof (UInt32) || type == typeof (UInt64)) {
- ulong value;
- try {
- value = UInt64.Parse (att); //FIXME: should use the culture specified in Page
- } catch (Exception){
- throw new ApplicationException (att + " is not a valid unsigned number " +
- "or is out of range.");
+ void TextParsed (ILocation location, string text)
+ {
+ if (text.IndexOf ("<%") != -1 && !inScript) {
+ if (this.text.Length > 0)
+ FlushText ();
+ CodeRenderParser r = new CodeRenderParser (text, stack.Builder);
+ r.AddChildren ();
+ return;
}
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
+ this.text.Append (text);
+ //PrintLocation (location);
}
- else if (type == typeof (float)) {
- float value;
- try {
- value = Single.Parse (att);
- } catch (Exception){
- throw new ApplicationException (att + " is not avalid float number or " +
- "is out of range.");
- }
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (double)){
- double value;
- try {
- value = Double.Parse (att);
- } catch (Exception){
- throw new ApplicationException (att + " is not avalid double number or " +
- "is out of range.");
+ void FlushText ()
+ {
+ string t = text.ToString ();
+ text.Length = 0;
+ if (inScript) {
+ // TODO: store location
+ tparser.Scripts.Add (t);
+ return;
}
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
- }
- else if (type == typeof (System.Drawing.Color)){
- Color c;
- try {
- c = (Color) TypeDescriptor.GetConverter (typeof (Color)).ConvertFromString (att);
- } catch (Exception e){
- throw new ApplicationException ("Color " + att + " is not a valid color.", e);
- }
+ if (tparser.DefaultDirectiveName == "application" && t.Trim () != "")
+ throw new ParseException (location, "Content not valid for application file.");
- // Should i also test for IsSystemColor?
- // Are KnownColor members in System.Drawing.Color?
- if (c.IsKnownColor){
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
- "{1};\n", var_name, c.Name);
- }
- else {
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
- "FromArgb ({1}, {2}, {3}, {4});\n",
- var_name, c.A, c.R, c.G, c.B);
- }
- }
- else {
- throw new ApplicationException ("Unsupported type in property: " +
- type.ToString ());
+ stack.Builder.AppendLiteralString (t);
}
- }
-
- private bool ProcessPropertiesAndFields (MemberInfo member, string id, TagAttributes att)
- {
- int hyphen = id.IndexOf ('-');
- bool isPropertyInfo = (member is PropertyInfo);
-
- bool is_processed = false;
- bool isDataBound = att.IsDataBound ((string) att [id]);
- Type type;
- if (isPropertyInfo) {
- type = ((PropertyInfo) member).PropertyType;
- if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
- return false;
- } else {
- type = ((FieldInfo) member).FieldType;
- }
+ bool ProcessTag (string tagid, TagAttributes atts)
+ {
+ if ((atts == null || !atts.IsRunAtServer ()) && String.Compare (tagid, "tbody", true) == 0) {
+ // MS completely ignores tbody or, if runat="server", fails when compiling
+ if (stack.Count > 0)
+ return stack.Builder.ChildrenAsProperties;
- if (0 == String.Compare (member.Name, id, true)){
- AddCodeForPropertyOrField (type, member.Name, (string) att [id], isDataBound);
- is_processed = true;
- } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
- string prop_field = id.Replace ("-", ".");
- string [] parts = prop_field.Split (new char [] {'.'});
- if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
return false;
-
- PropertyInfo [] subprops = type.GetProperties ();
- foreach (PropertyInfo subprop in subprops){
- if (0 != String.Compare (subprop.Name, parts [1], true))
- continue;
-
- if (subprop.CanWrite == false)
- return false;
-
- bool is_bool = subprop.PropertyType == typeof (bool);
- if (!is_bool && att [id] == null){
- att [id] = ""; // Font-Size -> Font-Size="" as html
- return false;
- }
-
- string value;
- if (att [id] == null && is_bool)
- value = "true"; // Font-Bold <=> Font-Bold="true"
- else
- value = (string) att [id];
-
- AddCodeForPropertyOrField (subprop.PropertyType,
- member.Name + "." + subprop.Name,
- value, isDataBound);
- is_processed = true;
}
- }
- return is_processed;
- }
-
- private void AddCodeForAttributes (Type type, TagAttributes att)
- {
- EventInfo [] ev_info = type.GetEvents ();
- PropertyInfo [] prop_info = type.GetProperties ();
- FieldInfo [] field_info = type.GetFields ();
- bool is_processed = false;
- ArrayList processed = new ArrayList ();
-
- foreach (string id in att.Keys){
- if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
- continue;
-
- if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
- string id_as_event = id.Substring (2);
- foreach (EventInfo ev in ev_info){
- if (0 == String.Compare (ev.Name, id_as_event, true)){
- current_function.AppendFormat (
- "\t\t\t__ctrl.{0} += " +
- "new {1} (this.{2});\n",
- ev.Name, ev.EventHandlerType, att [id]);
- is_processed = true;
- break;
- }
+ ControlBuilder parent = stack.Builder;
+ ControlBuilder builder = null;
+ BuilderLocation bl = null;
+ Hashtable htable = (atts != null) ? atts.GetDictionary (null) : emptyHash;
+ if (stack.Count > 1) {
+ try {
+ builder = parent.CreateSubBuilder (tagid, htable, null, tparser, location);
+ } catch (TypeLoadException e) {
+ throw new ParseException (Location, "Type not found.", e);
+ } catch (Exception e) {
+ throw new ParseException (Location, e.Message, e);
}
- if (is_processed){
- is_processed = false;
- continue;
- }
- }
-
- foreach (PropertyInfo prop in prop_info){
- is_processed = ProcessPropertiesAndFields (prop, id, att);
- if (is_processed)
- break;
}
- if (!is_processed) {
- foreach (FieldInfo field in field_info){
- is_processed = ProcessPropertiesAndFields (field, id, att);
- if (is_processed)
- break;
+ if (builder == null && atts != null && atts.IsRunAtServer ()) {
+ string id = htable ["id"] as string;
+ if (id != null && !CodeGenerator.IsValidLanguageIndependentIdentifier (id))
+ throw new ParseException (Location, "'" + id + "' is not a valid identifier");
+
+ try {
+ builder = rootBuilder.CreateSubBuilder (tagid, htable, null, tparser, location);
+ } catch (TypeLoadException e) {
+ throw new ParseException (Location, "Type not found.", e);
+ } catch (Exception e) {
+ throw new ParseException (Location, e.Message, e);
}
}
+
+ if (builder == null)
+ return false;
- if (is_processed){
- is_processed = false;
- continue;
+ builder.location = location;
+ builder.ID = htable ["id"] as string;
+ if (builder.HasBody ()) {
+ if (builder is TemplateBuilder) {
+ // push the id list
+ }
+ stack.Push (builder, location);
+ } else {
+ // FIXME:ObjectTags...
+ parent.AppendSubBuilder (builder);
+ builder.CloseControl ();
}
- current_function.AppendFormat ("\t\t\t((System.Web.UI.IAttributeAccessor) __ctrl)." +
- "SetAttribute (\"{0}\", \"{1}\");\n",
- id, Escape ((string) att [id]));
- }
- }
-
- private void AddCodeRenderControl (StringBuilder function)
- {
- AddCodeRenderControl (function, controls.CodeRenderIndex);
- }
-
- private void AddCodeRenderControl (StringBuilder function, int index)
- {
- function.AppendFormat ("\t\t\tparameterContainer.Controls [{0}]." +
- "RenderControl (__output);\n", index);
- }
-
- private void AddRenderMethodDelegate (StringBuilder function, string control_id)
- {
- function.AppendFormat ("\t\t\t__ctrl.SetRenderMethodDelegate (new System.Web." +
- "UI.RenderMethod (this.__Render_{0}));\n", control_id);
- }
-
- private void AddCodeRenderFunction (string codeRender, string control_id)
- {
- StringBuilder codeRenderFunction = new StringBuilder ();
- codeRenderFunction.AppendFormat ("\t\tprivate void __Render_{0} " +
- "(System.Web.UI.HtmlTextWriter __output, " +
- "System.Web.UI.Control parameterContainer)\n" +
- "\t\t{{\n", control_id);
- codeRenderFunction.Append (codeRender);
- codeRenderFunction.Append ("\t\t}\n\n");
- init_funcs.Append (codeRenderFunction);
- }
-
- private void RemoveLiterals (StringBuilder function)
- {
- string no_literals = Regex.Replace (function.ToString (),
- @"\t\t\t__parser.AddParsedSubObject \(" +
- @"new System.Web.UI.LiteralControl \(.+\);\n", "");
- function.Length = 0;
- function.Append (no_literals);
- }
-
- private bool FinishControlFunction (string tag_id)
- {
- if (functions.Count == 0)
- throw new ApplicationException ("Unbalanced open/close tags");
-
- if (controls.Count == 0)
- return false;
-
- string saved_id = controls.PeekTagID ();
- if (0 != String.Compare (saved_id, tag_id, true))
- return false;
-
- StringBuilder old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
-
- string control_id = controls.PeekControlID ();
- Type control_type = controls.PeekType ();
- ChildrenKind child_kind = controls.PeekChildKind ();
-
- bool hasDataBindFunction = controls.HasDataBindFunction ();
- if (hasDataBindFunction)
- old_function.AppendFormat ("\t\t\t__ctrl.DataBinding += new System.EventHandler " +
- "(this.__DataBind_{0});\n", control_id);
-
- bool useCodeRender = controls.UseCodeRender;
- if (useCodeRender)
- AddRenderMethodDelegate (old_function, control_id);
-
- if (control_type == typeof (System.Web.UI.ITemplate)){
- old_function.Append ("\n\t\t}\n\n");
- current_function.AppendFormat ("\t\t\t__ctrl.{0} = new System.Web.UI." +
- "CompiledTemplateBuilder (new System.Web.UI." +
- "BuildTemplateMethod (this.__BuildControl_{1}));\n",
- saved_id, control_id);
- }
- else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumnCollection)){
- old_function.Append ("\n\t\t}\n\n");
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
- control_id, saved_id);
+ return true;
}
- else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
- control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)) ||
- control_type == typeof (System.Web.UI.WebControls.ListItem)){
- old_function.Append ("\n\t\t}\n\n");
- string parsed = "";
- string ctrl_name = "ctrl";
- Type cont = controls.Container;
- if (cont == null || cont == typeof (System.Web.UI.HtmlControls.HtmlSelect)){
- parsed = "ParsedSubObject";
- ctrl_name = "parser";
- }
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
- "\t\t\t__{1}.Add{2} (this.{0});\n\n",
- control_id, ctrl_name, parsed);
- }
- else if (child_kind == ChildrenKind.LISTITEM){
- old_function.Append ("\n\t\t}\n\n");
- init_funcs.Append (old_function); // Closes the BuildList function
- old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
- old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
- "return __ctrl;\n\t\t}}\n\n",
- control_id, controls.PeekDefaultPropertyName ());
-
- controls.Pop ();
- control_id = controls.PeekControlID ();
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
- "AddParsedSubObject (this.{0});\n\n", control_id);
- } else if (control_type == typeof (HtmlTableCell)) {
- old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
- object top = controls.Pop ();
- Type t = controls.PeekType ();
- controls.Push (top);
- string parsed = "";
- string ctrl_name = "ctrl";
- if (t != typeof (HtmlTableRow)) {
- parsed = "ParsedSubObject";
- ctrl_name = "parser";
+ bool ProcessScript (TagType tagtype, TagAttributes attributes)
+ {
+ if (tagtype != TagType.Close) {
+ if (attributes != null && attributes.IsRunAtServer ()) {
+ CheckLanguage ((string) attributes ["language"]);
+ if (tagtype == TagType.Tag) {
+ Parser.VerbatimID = "script";
+ inScript = true;
+ } //else if (tagtype == TagType.SelfClosing)
+ // load script file here
+
+ return true;
+ } else {
+ Parser.VerbatimID = "script";
+ javascript = true;
+ TextParsed (location, location.PlainText);
+ return true;
+ }
}
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
- "\t\t\t__{1}.Add{2} (this.{0});\n\n",
- control_id, ctrl_name, parsed);
- } else if (child_kind == ChildrenKind.HTMLROW || child_kind == ChildrenKind.HTMLCELL) {
- old_function.Append ("\n\t\t}\n\n");
- init_funcs.Append (old_function);
- old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
- old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
- "return __ctrl;\n\t\t}}\n\n",
- control_id, controls.PeekDefaultPropertyName ());
-
- controls.Pop ();
- control_id = controls.PeekControlID ();
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n", control_id);
- if (child_kind == ChildrenKind.HTMLROW) {
- current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject ({0});\n",
- control_id);
+ bool result;
+ if (inScript) {
+ result = inScript;
+ inScript = false;
} else {
- current_function.AppendFormat ("\t\t\t__ctrl.Add (this.{0});\n", control_id);
+ result = javascript;
+ javascript = false;
+ TextParsed (location, location.PlainText);
}
- } else {
- old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
- "AddParsedSubObject (this.{0});\n\n", control_id);
- }
-
- if (useCodeRender)
- RemoveLiterals (old_function);
- init_funcs.Append (old_function);
- if (useCodeRender)
- AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), control_id);
-
- if (hasDataBindFunction){
- StringBuilder db_function = controls.DataBindFunction;
- db_function.Append ("\t\t}\n\n");
- init_funcs.Append (db_function);
+ return result;
}
- // Avoid getting empty stacks for unbalanced open/close tags
- if (controls.Count > 1){
- controls.Pop ();
- AddCodeRenderControl (controls.CodeRenderFunction, controls.ChildIndex);
- }
-
- return true;
- }
-
- private void NewTableElementFunction (HtmlControlTag ctrl)
- {
- string control_id = Tag.GetDefaultID ();
- ChildrenKind child_kind;
-
- Type t;
- if (ctrl.ControlType == typeof (HtmlTable)) {
- t = typeof (HtmlTableRowCollection);
- child_kind = ChildrenKind.HTMLROW;
- } else {
- t = typeof (HtmlTableCellCollection);
- child_kind = ChildrenKind.HTMLCELL;
- }
-
- controls.Push (ctrl.ControlType,
- control_id,
- ctrl.TagID,
- child_kind,
- ctrl.ParseChildren);
-
-
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
- "\t\t{{\n", control_id, t);
- }
-
- private void ProcessHtmlControlTag ()
- {
- HtmlControlTag html_ctrl = (HtmlControlTag) elements.Current;
- if (html_ctrl.TagID.ToUpper () == "SCRIPT"){
- //FIXME: if the is script is to be read from disk, do it!
- if (html_ctrl.SelfClosing)
- throw new ApplicationException ("Read script from file not supported yet.");
-
- if (elements.MoveNext () == false)
- throw new ApplicationException ("Error after " + html_ctrl.ToString ());
-
- if (elements.Current is PlainText){
- script.Append (((PlainText) elements.Current).Text);
- if (!elements.MoveNext ())
- throw new ApplicationException ("Error after " +
- elements.Current.ToString ());
- }
-
- if (elements.Current is CloseTag)
- elements.MoveNext ();
- return;
- } else if (IsApplication) {
- throw new ApplicationException (app_file_wrong);
- }
-
- Type controlType = html_ctrl.ControlType;
- AddProtectedField (controlType, html_ctrl.ControlID);
-
- ChildrenKind children_kind;
- if (0 == String.Compare (html_ctrl.TagID, "table", true))
- children_kind = ChildrenKind.HTMLROW;
- else if (0 == String.Compare (html_ctrl.TagID, "tr", true))
- children_kind = ChildrenKind.HTMLCELL;
- else if (0 != String.Compare (html_ctrl.TagID, "select", true))
- children_kind = html_ctrl.IsContainer ? ChildrenKind.CONTROLS :
- ChildrenKind.NONE;
- else
- children_kind = ChildrenKind.OPTION;
-
- NewControlFunction (html_ctrl.TagID, html_ctrl.ControlID, controlType, children_kind, html_ctrl.ParseChildren);
-
- current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", html_ctrl.ControlID);
- AddCodeForAttributes (html_ctrl.ControlType, html_ctrl.Attributes);
-
- if (children_kind == ChildrenKind.HTMLROW || children_kind == ChildrenKind.HTMLCELL)
- NewTableElementFunction (html_ctrl);
-
- if (!html_ctrl.SelfClosing)
- JustDoIt ();
- else
- FinishControlFunction (html_ctrl.TagID);
- }
-
- // Closing is performed in FinishControlFunction ()
- private void NewBuildListFunction (AspComponent component)
- {
- string control_id = Tag.GetDefaultID ();
-
- controls.Push (component.ComponentType,
- control_id,
- component.TagID,
- ChildrenKind.LISTITEM,
- component.DefaultPropertyName);
-
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
- "(System.Web.UI.WebControls.ListItemCollection __ctrl)\n" +
- "\t\t{{\n", control_id);
- }
-
- private void ProcessComponent ()
- {
- AspComponent component = (AspComponent) elements.Current;
- Type component_type = component.ComponentType;
- AddProtectedField (component_type, component.ControlID);
-
- NewControlFunction (component.TagID, component.ControlID, component_type,
- component.ChildrenKind, component.DefaultPropertyName);
-
- if (component_type.IsSubclassOf (typeof (System.Web.UI.UserControl)))
- current_function.Append ("\t\t\t__ctrl.InitializeAsUserControl (Page);\n");
-
- if (component_type.IsSubclassOf (typeof (System.Web.UI.Control)))
- current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", component.ControlID);
-
- AddCodeForAttributes (component.ComponentType, component.Attributes);
- if (component.ChildrenKind == ChildrenKind.LISTITEM)
- NewBuildListFunction (component);
-
- if (!component.SelfClosing)
- JustDoIt ();
- else
- FinishControlFunction (component.TagID);
- }
-
- private void ProcessServerObjectTag ()
- {
- ServerObjectTag obj = (ServerObjectTag) elements.Current;
- declarations.AppendFormat ("\t\tprivate {0} cached{1};\n", obj.ObjectClass, obj.ObjectID);
- constructor.AppendFormat ("\n\t\tprivate {0} {1}\n\t\t{{\n\t\t\tget {{\n\t\t\t\t" +
- "if (this.cached{1} == null)\n\t\t\t\t\tthis.cached{1} = " +
- "new {0} ();\n\t\t\t\treturn cached{1};\n\t\t\t}}\n\t\t}}\n\n",
- obj.ObjectClass, obj.ObjectID);
- }
-
- // Creates a new function that sets the values of subproperties.
- private void NewStyleFunction (PropertyTag tag)
- {
- current_function = new StringBuilder ();
-
- string prop_id = tag.PropertyID;
- Type prop_type = tag.PropertyType;
- // begin function
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
- "\t\t{{\n", prop_id, prop_type);
-
- // Add property initialization code
- PropertyInfo [] subprop_info = prop_type.GetProperties ();
- TagAttributes att = tag.Attributes;
-
- string subprop_name = null;
- foreach (string id in att.Keys){
- if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
- continue;
-
- bool is_processed = false;
- foreach (PropertyInfo subprop in subprop_info){
- is_processed = ProcessPropertiesAndFields (subprop, id, att);
- if (is_processed){
- subprop_name = subprop.Name;
- break;
+ bool CloseControl (string tagid)
+ {
+ ControlBuilder current = stack.Builder;
+ if (String.Compare (tagid, "tbody", true) == 0) {
+ if (!current.ChildrenAsProperties) {
+ try {
+ TextParsed (location, location.PlainText);
+ FlushText ();
+ } catch {}
}
+ return true;
}
+
+ string btag = current.TagName;
+ if (0 != String.Compare (tagid, btag, true))
+ return false;
- if (subprop_name == null)
- throw new ApplicationException ("Property " + tag.TagID + " does not have " +
- "a " + id + " subproperty.");
- }
-
- // Finish function
- current_function.Append ("\n\t\t}\n\n");
- init_funcs.Append (current_function);
- current_function = (StringBuilder) functions.Peek ();
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
- prop_id, tag.PropertyName);
-
- if (!tag.SelfClosing){
- // Next tag should be the closing tag
- controls.Push (null, null, null, ChildrenKind.NONE, null);
- bool closing_tag_found = false;
- Element elem;
- while (!closing_tag_found && elements.MoveNext ()){
- elem = (Element) elements.Current;
- if (elem is PlainText)
- ProcessPlainText ();
- else if (!(elem is CloseTag))
- throw new ApplicationException ("Tag " + tag.TagID +
- " not properly closed.");
- else
- closing_tag_found = true;
- }
-
- if (!closing_tag_found)
- throw new ApplicationException ("Tag " + tag.TagID + " not properly closed.");
-
- controls.Pop ();
+ // if (current is TemplateBuilder)
+ // pop from the id list
+ current.CloseControl ();
+ stack.Pop ();
+ stack.Builder.AppendSubBuilder (current);
+ return true;
}
- }
-
- // This one just opens the function. Closing is performed in FinishControlFunction ()
- private void NewTemplateFunction (PropertyTag tag)
- {
- /*
- * FIXME
- * This function does almost the same as NewControlFunction.
- * Consider merging.
- */
- string prop_id = tag.PropertyID;
- Type prop_type = tag.PropertyType;
- string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
-
- controls.Push (prop_type, prop_id, tag_id, ChildrenKind.CONTROLS, null);
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
- "(System.Web.UI.Control __ctrl)\n" +
- "\t\t{{\n" +
- "\t\t\tSystem.Web.UI.IParserAccessor __parser " +
- "= (System.Web.UI.IParserAccessor) __ctrl;\n" , prop_id);
- }
-
- // Closing is performed in FinishControlFunction ()
- private void NewDBColumnFunction (PropertyTag tag)
- {
- /*
- * FIXME
- * This function also does almost the same as NewControlFunction.
- * Consider merging.
- */
- string prop_id = tag.PropertyID;
- Type prop_type = tag.PropertyType;
- string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
-
- controls.Push (prop_type, prop_id, tag_id, ChildrenKind.DBCOLUMNS, null);
- current_function = new StringBuilder ();
- functions.Push (current_function);
- current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
- "(System.Web.UI.WebControls.DataGridColumnCollection __ctrl)\n" +
- "\t\t{{\n", prop_id);
- }
- private void NewPropertyFunction (PropertyTag tag)
- {
- if (tag.PropertyType == typeof (System.Web.UI.WebControls.Style) ||
- tag.PropertyType.IsSubclassOf (typeof (System.Web.UI.WebControls.Style)))
- NewStyleFunction (tag);
- else if (tag.PropertyType == typeof (System.Web.UI.ITemplate))
- NewTemplateFunction (tag);
- else if (tag.PropertyType == typeof (System.Web.UI.WebControls.DataGridColumnCollection))
- NewDBColumnFunction (tag);
- else
- throw new ApplicationException ("Other than Style and ITemplate not supported yet. " +
- tag.PropertyType);
- }
-
- private void ProcessHtmlTag ()
- {
- Tag tag = (Tag) elements.Current;
- ChildrenKind child_kind = controls.PeekChildKind ();
- if (child_kind == ChildrenKind.NONE){
- string tag_id = controls.PeekTagID ();
- throw new ApplicationException (tag + " not allowed inside " + tag_id);
- }
-
- if (child_kind == ChildrenKind.OPTION){
- if (0 != String.Compare (tag.TagID, "option", true))
- throw new ApplicationException ("Only <option> tags allowed inside <select>.");
-
- string default_id = Tag.GetDefaultID ();
- Type type = typeof (System.Web.UI.WebControls.ListItem);
- AddProtectedField (type, default_id);
- NewControlFunction (tag.TagID, default_id, type, ChildrenKind.CONTROLS, null);
- return;
- }
+ bool ProcessCode (TagType tagtype, string code, ILocation location)
+ {
+ ControlBuilder b = null;
+ if (tagtype == TagType.CodeRender)
+ b = new CodeRenderBuilder (code, false, location);
+ else if (tagtype == TagType.CodeRenderExpression)
+ b = new CodeRenderBuilder (code, true, location);
+ else if (tagtype == TagType.DataBinding)
+ b = new DataBindingBuilder (code, location);
+ else
+ throw new HttpException ("Should never happen");
- if (child_kind == ChildrenKind.CONTROLS) {
- ArrayList tag_elements = tag.GetElements ();
- foreach (Element e in tag_elements) {
- if (e is PlainText) {
- elements.Current = e;
- ProcessPlainText ();
- } else if (e is CodeRenderTag) {
- elements.Current = e;
- ProcessCodeRenderTag ();
- } else if (e is DataBindingTag) {
- elements.Current = e;
- ProcessDataBindingLiteral ();
- } else {
- throw new ApplicationException (fullPath + ": unexpected tag type " + e.GetType ());
- }
- }
- return;
+ stack.Builder.AppendSubBuilder (b);
+ return true;
}
- if (child_kind == ChildrenKind.HTMLROW) {
- if (0 == String.Compare (tag.TagID, "tr", true)) {
- elements.Current = new HtmlControlTag (tag);
- ProcessHtmlControlTag ();
- return;
- }
+ public ILocation Location {
+ get { return location; }
}
- if (child_kind == ChildrenKind.HTMLCELL) {
- if (0 == String.Compare (tag.TagID, "td", true)) {
- elements.Current = new HtmlControlTag (tag);
- ProcessHtmlControlTag ();
+ void CheckLanguage (string lang)
+ {
+ if (lang == null || lang == "")
return;
- }
- }
- // Now child_kind should be PROPERTIES, so only allow tag_id == property
- Type control_type = controls.PeekType ();
- PropertyInfo [] prop_info = control_type.GetProperties ();
- bool is_processed = false;
- foreach (PropertyInfo prop in prop_info){
- if (0 == String.Compare (prop.Name, tag.TagID, true)){
- PropertyTag prop_tag = new PropertyTag (tag, prop.PropertyType, prop.Name);
- NewPropertyFunction (prop_tag);
- is_processed = true;
- break;
+ if (String.Compare (lang, tparser.Language, true) != 0) {
+ throw new ParseException (Location,
+ String.Format ("Trying to mix language '{0}' and '{1}'.",
+ tparser.Language, lang));
}
}
-
- if (!is_processed){
- string tag_id = controls.PeekTagID ();
- throw new ApplicationException (tag.TagID + " is not a property of " + control_type);
- }
- }
+ // Used to get CodeRender tags in attribute values
+ class CodeRenderParser
+ {
+ string str;
+ ControlBuilder builder;
- private Tag Map (Tag tag)
- {
- int pos = tag.TagID.IndexOf (":");
- if (pos == -1) {
- ChildrenKind child_kind = controls.PeekChildKind ();
- if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
- tag.Attributes.Add ("runat", "server");
- return new HtmlControlTag (tag);
- } else if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
- tag.Attributes.Add ("runat", "server");
- return new HtmlControlTag (tag);
+ public CodeRenderParser (string str, ControlBuilder builder)
+ {
+ this.str = str;
+ this.builder = builder;
}
- }
-
- if (tag is CloseTag ||
- ((tag.Attributes == null ||
- !tag.Attributes.IsRunAtServer ()) && pos == -1))
- return tag;
-
- if (pos == -1){
- if (0 == String.Compare (tag.TagID, "object", true))
- return new ServerObjectTag (tag);
-
- return new HtmlControlTag (tag);
- }
-
- string foundry_name = tag.TagID.Substring (0, pos);
- string component_name = tag.TagID.Substring (pos + 1);
-
- if (Foundry.LookupFoundry (foundry_name) == false)
- throw new ApplicationException ("Cannot find foundry for alias'" + foundry_name + "'");
-
- AspComponent component = Foundry.MakeAspComponent (foundry_name, component_name, tag);
- if (component == null)
- throw new ApplicationException ("Cannot find component '" + component_name +
- "' for alias '" + foundry_name + "'");
-
- return component;
- }
-
- private void ProcessCloseTag ()
- {
- CloseTag close_tag = (CloseTag) elements.Current;
- if (FinishControlFunction (close_tag.TagID))
- return;
- elements.Current = new PlainText (close_tag.PlainHtml);
- ProcessPlainText ();
- }
-
- private void ProcessDataBindingLiteral ()
- {
- DataBindingTag dataBinding = (DataBindingTag) elements.Current;
- string actual_value = dataBinding.Data;
- if (actual_value == "")
- throw new ApplicationException ("Empty data binding tag.");
-
- if (controls.PeekChildKind () != ChildrenKind.CONTROLS)
- throw new ApplicationException ("Data bound content not allowed for " +
- controls.PeekTagID ());
-
- StringBuilder db_function = new StringBuilder ();
- string control_id = Tag.GetDefaultID ();
- string control_type_string = "System.Web.UI.DataBoundLiteralControl";
- AddProtectedField (typeof (System.Web.UI.DataBoundLiteralControl), control_id);
- // Build the control
- db_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_{0} ()\n" +
- "\t\t{{\n\t\t\t{1} __ctrl;\n\n" +
- "\t\t\t__ctrl = new {1} (0, 1);\n" +
- "\t\t\tthis.{0} = __ctrl;\n" +
- "\t\t\t__ctrl.DataBinding += new System.EventHandler " +
- "(this.__DataBind_{0});\n" +
- "\t\t\treturn __ctrl;\n"+
- "\t\t}}\n\n",
- control_id, control_type_string);
- // DataBinding handler
- db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
- "System.EventArgs e) {{\n" +
- "\t\t\t{1} Container;\n" +
- "\t\t\t{2} target;\n" +
- "\t\t\ttarget = ({2}) sender;\n" +
- "\t\t\tContainer = ({1}) target.BindingContainer;\n" +
- "\t\t\ttarget.SetDataBoundString (0, System.Convert." +
- "ToString ({3}));\n" +
- "\t\t}}\n\n",
- control_id, controls.Container, control_type_string,
- actual_value);
-
- init_funcs.Append (db_function);
- current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
- "AddParsedSubObject (this.{0});\n\n", control_id);
-
- AddCodeRenderControl (controls.CodeRenderFunction);
- }
-
- private void ProcessCodeRenderTag ()
- {
- CodeRenderTag code_tag = (CodeRenderTag) elements.Current;
-
- controls.UseCodeRender = true;
- if (code_tag.IsVarName)
- controls.CodeRenderFunction.AppendFormat ("\t\t\t__output.Write ({0});\n",
- code_tag.Code);
- else
- controls.CodeRenderFunction.AppendFormat ("\t\t\t{0}\n", code_tag.Code);
- }
-
- public void ProcessElements ()
- {
- JustDoIt ();
- End ();
- parse_ok = true;
- }
-
- private void JustDoIt ()
- {
- Element element;
-
- while (elements.MoveNext ()){
- element = (Element) elements.Current;
- if (element is Directive){
- ProcessDirective ();
- } else if (element is PlainText){
- ProcessPlainText ();
- } else if (element is DataBindingTag){
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
- ProcessDataBindingLiteral ();
- } else if (element is CodeRenderTag){
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
- ProcessCodeRenderTag ();
- } else {
- elements.Current = Map ((Tag) element);
- if (elements.Current is ServerObjectTag) {
- ProcessServerObjectTag ();
- continue;
- }
-
- if (elements.Current is HtmlControlTag) {
- ProcessHtmlControlTag ();
- continue;
+ public void AddChildren ()
+ {
+ int index = str.IndexOf ("<%");
+ if (index > 0) {
+ TextParsed (null, str.Substring (0, index));
+ str = str.Substring (index);
}
- if (IsApplication)
- throw new ApplicationException (app_file_wrong);
-
- else if (elements.Current is AspComponent)
- ProcessComponent ();
- else if (elements.Current is CloseTag)
- ProcessCloseTag ();
- else if (elements.Current is Tag)
- ProcessHtmlTag ();
+ AspParser parser = new AspParser ("@@inner_string@@", new StringReader (str));
+ parser.Error += new ParseErrorHandler (ParseError);
+ parser.TagParsed += new TagParsedHandler (TagParsed);
+ parser.TextParsed += new TextParsedHandler (TextParsed);
+ parser.Parse ();
+ }
+
+ void TagParsed (ILocation location, TagType tagtype, string tagid, TagAttributes attributes)
+ {
+ if (tagtype == TagType.CodeRender)
+ builder.AppendSubBuilder (new CodeRenderBuilder (tagid, false, location));
+ else if (tagtype == TagType.CodeRenderExpression)
+ builder.AppendSubBuilder (new CodeRenderBuilder (tagid, true, location));
+ else if (tagtype == TagType.DataBinding)
+ builder.AppendSubBuilder (new DataBindingBuilder (tagid, location));
else
- throw new ApplicationException ("This place should not be reached.");
+ builder.AppendLiteralString (location.PlainText);
}
- }
- }
- private string GetTemplateDirectory ()
- {
- string templatePath = Path.GetDirectoryName (fullPath);
- string appPath = Path.GetDirectoryName (HttpRuntime.AppDomainAppPath);
-
- if (templatePath == appPath)
- return "/";
-
- templatePath = templatePath.Substring (appPath.Length);
- if (Path.DirectorySeparatorChar != '/')
- templatePath = templatePath.Replace (Path.DirectorySeparatorChar, '/');
-
- return templatePath;
- }
-
- private void End ()
- {
- if (isPage) {
- if (sessionState == SessionState.Enabled || sessionState == SessionState.ReadOnly)
- AddInterface (typeof (System.Web.SessionState.IRequiresSessionState));
-
- if (sessionState == SessionState.ReadOnly)
- AddInterface (typeof (System.Web.SessionState.IReadOnlySessionState));
- }
-
- classDecl = "\tpublic class " + className + " : " + parent + interfaces + " {\n";
- prolog.Append ("\n" + classDecl);
- declarations.Append ("\t\tprivate static bool __intialized = false;\n\n");
- if (IsPage)
- declarations.Append ("\t\tprivate static ArrayList __fileDependencies;\n\n");
-
- // adds the constructor
- constructor.AppendFormat ("\t\tpublic {0} ()\n\t\t{{\n", className);
- if (!IsApplication)
- constructor.Append ("\t\t\tSystem.Collections.ArrayList dependencies;\n\n");
-
- constructor.AppendFormat ("\t\t\tif (ASP.{0}.__intialized == false){{\n", className);
-
- if (IsPage) {
- constructor.AppendFormat ("\t\t\t\tdependencies = new System.Collections.ArrayList ();\n" +
- "\t\t\t\tdependencies.Add (@\"{1}\");\n" +
- "\t\t\t\tASP.{0}.__fileDependencies = dependencies;\n",
- className, fullPath);
- }
-
- constructor.AppendFormat ("\t\t\t\tASP.{0}.__intialized = true;\n\t\t\t}}\n\t\t}}\n\n",
- className);
-
- if (!IsApplication) {
- //FIXME: add AutoHandlers: don't know what for...yet!
- constructor.AppendFormat (
- "\t\tprotected override int AutoHandlers\n\t\t{{\n" +
- "\t\t\tget {{ return ASP.{0}.__autoHandlers; }}\n" +
- "\t\t\tset {{ ASP.{0}.__autoHandlers = value; }}\n" +
- "\t\t}}\n\n", className);
-
- constructor.Append (
- "\t\tprotected System.Web.HttpApplication ApplicationInstance\n\t\t{\n" +
- "\t\t\tget { return (System.Web.HttpApplication) this.Context.ApplicationInstance; }\n" +
- "\t\t}\n\n");
-
- constructor.AppendFormat (
- "\t\tpublic override string TemplateSourceDirectory\n\t\t{{\n" +
- "\t\t\tget {{ return \"{0}\"; }}\n" +
- "\t\t}}\n\n", GetTemplateDirectory ());
-
- epilog.Append ("\n\t\tprotected override void FrameworkInitialize ()\n\t\t{\n" +
- "\t\t\tthis.__BuildControlTree (this);\n");
-
- if (IsPage) {
- epilog.AppendFormat ("\t\t\tthis.FileDependencies = ASP.{0}.__fileDependencies;\n" +
- "\t\t\tthis.EnableViewStateMac = true;\n", className);
+ void TextParsed (ILocation location, string text)
+ {
+ builder.AppendLiteralString (text);
}
- epilog.Append ("\t\t}\n\n");
- }
-
- if (IsPage) {
- Random rnd = new Random ();
- epilog.AppendFormat ("\t\tpublic override int GetTypeHashCode ()\n\t\t{{\n" +
- "\t\t\treturn {0};\n" +
- "\t\t}}\n", rnd.Next ());
- }
-
- epilog.Append ("\t}\n}\n");
-
- // Closes the currently opened tags
- StringBuilder old_function = current_function;
- string control_id;
- while (functions.Count > 1){
- old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
- init_funcs.Append (old_function);
- control_id = controls.PeekControlID ();
- FinishControlFunction (control_id);
- controls.AddChild ();
- old_function = (StringBuilder) functions.Pop ();
- current_function = (StringBuilder) functions.Peek ();
- controls.Pop ();
- }
-
- bool useCodeRender = controls.UseCodeRender;
- if (useCodeRender){
- RemoveLiterals (current_function);
- AddRenderMethodDelegate (current_function, controls.PeekControlID ());
- }
-
- current_function.Append ("\t\t}\n\n");
- init_funcs.Append (current_function);
- if (useCodeRender)
- AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), controls.PeekControlID ());
-
- functions.Pop ();
- }
-
- //
- // Functions related to compilation of user controls
- //
-
- private static char dirSeparator = Path.DirectorySeparatorChar;
- struct UserControlData
- {
- public UserControlResult result;
- public string className;
- public string assemblyName;
- }
-
- private static UserControlData GenerateUserControl (string src, HttpContext context)
- {
- UserControlData data = new UserControlData ();
- data.result = UserControlResult.OK;
-
- UserControlCompiler compiler = new UserControlCompiler (new UserControlParser (src, context));
- Type t = compiler.GetCompiledType ();
- if (t == null) {
- data.result = UserControlResult.CompilationFailed;
- return data;
+ void ParseError (ILocation location, string message)
+ {
+ throw new ParseException (location, message);
+ }
}
-
- data.className = t.Name;
- data.assemblyName = compiler.TargetFile;
-
- return data;
}
}
-}
-