Files
ZuneShell.dll/UIX/Microsoft/Iris/Markup/Parser.cs
T

382 lines
20 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Microsoft.Iris.Markup.Parser
// Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
// MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11
// Assembly location: C:\Program Files\Zune\UIX.dll
using Microsoft.Iris.Data;
using Microsoft.Iris.Markup.Validation;
using Microsoft.Iris.OS;
using Microsoft.Iris.Session;
using SSVParseLib;
using System.Collections;
using System.Xml;
namespace Microsoft.Iris.Markup
{
internal class Parser
{
private static ParserLexClass s_lex;
private static ParserYaccClass s_yacc;
private static SSLexTable s_lexTable;
private static SSYaccTable s_yaccTable;
private static bool s_parserActive;
public static ParseResult Invoke(SourceMarkupLoader owner, Resource resource)
{
ErrorWatermark watermark = ErrorManager.Watermark;
ParseResult parseResult = new ParseResult();
Stack parseStack = new Stack();
bool flag = false;
bool additionalMetadata = MarkupSystem.TrackAdditionalMetadata;
using (ManagedXmlReader xmlReader = new ManagedXmlReader(resource))
{
try
{
string str1 = string.Empty;
XmlNodeType nodeType;
while (xmlReader.Read(out nodeType))
{
if (parseResult.Root == null || parseStack.Count == 0 && nodeType == XmlNodeType.EndElement)
{
if (nodeType == XmlNodeType.Element)
{
parseResult.Root = xmlReader.Name;
while (xmlReader.ReadAttribute())
{
string name = xmlReader.Name;
string prefix = xmlReader.Prefix;
if (name == "xmlns")
parseResult.Version = xmlReader.Value;
else if (prefix == "xmlns")
{
ValidateNamespace validateNamespace = new ValidateNamespace(owner, xmlReader.LocalName, xmlReader.Value, xmlReader.LineNumber, xmlReader.LinePosition);
if (parseResult.XmlnsList == null)
parseResult.XmlnsList = validateNamespace;
else
parseResult.XmlnsList.AppendToEnd(validateNamespace);
}
else
ReportError(xmlReader, "Unexpected attribute '{0}' on root tag", name);
}
}
}
else
{
switch (nodeType)
{
case XmlNodeType.Element:
if (flag)
{
ReportError(xmlReader, "Script tag may not contain XML elements, found: '{0}'", xmlReader.Name);
continue;
}
bool isEmptyElement = xmlReader.IsEmptyElement;
string prefix1 = xmlReader.Prefix;
string localName = xmlReader.LocalName;
if (parseStack.Count % 2 == 0)
{
if (prefix1 == "" && localName == "Script")
{
flag = true;
parseStack.Push(new Parser.ScriptBlock(xmlReader.LineNumber, xmlReader.LinePosition));
if (xmlReader.ReadAttribute())
ReportError(xmlReader, "Script tag may not have XML attributes");
}
else
{
ValidateTypeIdentifier typeIdentifier = new ValidateTypeIdentifier(owner, prefix1, localName, xmlReader.LineNumber, xmlReader.LinePosition);
bool isRootTag = parseStack.Count == 0;
ValidateObjectTag objectTagValidator = owner.CreateObjectTagValidator(typeIdentifier, xmlReader.LineNumber, xmlReader.LinePosition, isRootTag);
while (xmlReader.ReadAttribute())
{
if (xmlReader.Prefix == string.Empty)
{
ValidateObject objectFromString = CreateValidateObjectFromString(owner, xmlReader);
ValidateProperty property = new ValidateProperty(owner, xmlReader.LocalName, objectFromString, xmlReader.LineNumber, xmlReader.LinePosition);
objectTagValidator.AddProperty(property);
}
else
ReportError(xmlReader, "Property or Object tag may not have prefixed attributes: '{0}'", xmlReader.Name);
}
parseStack.Push(objectTagValidator);
if (additionalMetadata && !string.IsNullOrEmpty(str1))
{
objectTagValidator.Metadata.Comments = str1;
str1 = string.Empty;
}
}
}
else
{
if (prefix1 != string.Empty)
ReportError(xmlReader, "Property tag may not be prefixed: '{0}'", xmlReader.Name);
if (localName == "Methods")
{
flag = true;
parseStack.Push(new Parser.ScriptBlock(xmlReader.LineNumber, xmlReader.LinePosition, CodeType.Methods));
if (xmlReader.ReadAttribute())
ReportError(xmlReader, "Script tag may not have XML attributes");
}
else
{
ValidateProperty validateProperty = new ValidateProperty(owner, localName, xmlReader.LineNumber, xmlReader.LinePosition);
while (xmlReader.ReadAttribute())
{
if (xmlReader.Prefix == string.Empty)
validateProperty.AddAttribute(new PropertyAttribute()
{
Name = xmlReader.LocalName,
Value = xmlReader.Value
});
else
ReportError(xmlReader, "Property or Object tag may not have prefixed attributes: '{0}'", xmlReader.Name);
}
parseStack.Push(validateProperty);
}
}
if (isEmptyElement)
{
flag = false;
HandleEndElement(owner, parseResult, parseStack);
continue;
}
continue;
case XmlNodeType.Text:
case XmlNodeType.CDATA:
if (parseStack.Count == 0)
{
ReportError(xmlReader, "Text/CDATA is not allowed under root tag ('{0}')", xmlReader.Value.Trim());
continue;
}
switch (parseStack.Peek())
{
case ValidateProperty validateProperty:
if (validateProperty.Value == null)
{
validateProperty.Value = CreateValidateObjectFromString(owner, xmlReader);
continue;
}
if (validateProperty.Value is ValidateFromString)
{
ReportError(xmlReader, "Property tag may only contain one Text/CDATA, found more text: '{0}'", xmlReader.Value.Trim());
continue;
}
ReportError(xmlReader, "Property tag already has objects, may not also add Text/CDATA: '{0}'", xmlReader.Value.Trim());
continue;
case Parser.ScriptBlock scriptBlock:
if (scriptBlock.ValidateValue == null)
{
scriptBlock.ValidateValue = ParseCode(owner, xmlReader, scriptBlock.CodeType);
continue;
}
ReportError(xmlReader, "Script tag may only contain one Text/CDATA, found more text: '{0}'", xmlReader.Value.Trim());
continue;
default:
ReportError(xmlReader, "Object tag may not contain Text/CDATA: '{0}'", xmlReader.Value.Trim());
continue;
}
case XmlNodeType.Comment:
string str2 = null;
if (additionalMetadata)
{
str2 = xmlReader.Value;
str1 = str1 + '\n' + str2;
}
if (flag)
{
if (str2 == null)
str2 = xmlReader.Value;
ReportError(xmlReader, "Script tag may not contain XML comments, found: '{0}'", str2.Trim());
continue;
}
continue;
case XmlNodeType.EndElement:
flag = false;
HandleEndElement(owner, parseResult, parseStack);
continue;
default:
continue;
}
}
}
}
catch (NativeXmlException ex)
{
ErrorManager.ReportError(ex.LineNumber, ex.LinePosition, ex.Message);
}
}
if (watermark.ErrorsDetected)
{
parseResult = new ParseResult();
parseResult.HasErrors = true;
}
return parseResult;
}
private static void HandleEndElement(
SourceMarkupLoader owner,
ParseResult parseResult,
Stack parseStack)
{
if (parseStack.Count % 2 == 1)
{
object obj = parseStack.Pop();
bool flag = false;
ValidateObject validateObject;
// FIXME
ScriptBlock scriptBlock = null;
if (obj is Parser.ScriptBlock)
{
scriptBlock = (Parser.ScriptBlock)obj;
validateObject = (ValidateObject)scriptBlock.ValidateValue;
}
else
{
validateObject = (ValidateObject)obj;
flag = true;
}
if (parseStack.Count == 0)
{
switch (validateObject)
{
case ValidateClass validateClass:
parseResult.ClassList.Add(validateClass);
break;
case ValidateAlias validateAlias:
if (parseResult.AliasList == ParseResult.s_EmptyAliasList)
parseResult.AliasList = new Vector<ValidateAlias>(4);
parseResult.AliasList.Add(validateAlias);
break;
case ValidateDataMapping validateDataMapping:
if (parseResult.DataMappingList == ParseResult.s_EmptyDataMappingList)
parseResult.DataMappingList = new Vector<ValidateDataMapping>(4);
parseResult.DataMappingList.Add(validateDataMapping);
break;
default:
if (flag)
{
ValidateObjectTag validateObjectTag = (ValidateObjectTag)validateObject;
ErrorManager.ReportError(validateObjectTag.Line, validateObjectTag.Column, "Unexpected root element '{0}', must be <Class>, <UI> or <Alias>", validateObjectTag.TypeIdentifier.TypeName);
break;
}
ErrorManager.ReportError(scriptBlock.Line, scriptBlock.Column, "Unexpected root element '{0}', must be <Class>, <UI> or <Alias>", "Script");
break;
}
}
else if (validateObject != null)
((ValidateProperty)parseStack.Peek()).AddValue(validateObject);
if (!flag)
return;
((ValidateObjectTag)validateObject).NotifyParseComplete();
}
else
{
object obj = parseStack.Pop();
ValidateProperty property = obj as ValidateProperty;
ValidateObjectTag validateObjectTag = (ValidateObjectTag)parseStack.Peek();
if (property != null)
{
validateObjectTag.AddProperty(property);
}
else
{
Parser.ScriptBlock scriptBlock = (Parser.ScriptBlock)obj;
if (validateObjectTag is ValidateClass validateClass)
validateClass.NotifyFoundMethodList((ValidateMethodList)scriptBlock.ValidateValue);
else
ErrorManager.ReportError(scriptBlock.ValidateValue.Line, scriptBlock.ValidateValue.Column, "Methods allowed only on <Class>, <UI> and <Effect>");
}
}
}
private static ValidateObject CreateValidateObjectFromString(
SourceMarkupLoader owner,
ManagedXmlReader xmlReader)
{
if (xmlReader.IsInlineExpression)
return (ValidateObject)ParseCode(owner, xmlReader, CodeType.InlineExpression);
string fromString = xmlReader.Value;
bool expandEscapes = true;
if (fromString.Length > 0 && fromString[0] == '@')
{
fromString = fromString.Substring(1);
expandEscapes = false;
}
return new ValidateFromString(owner, fromString, expandEscapes, xmlReader.LineNumber, xmlReader.LinePosition);
}
private static Validate ParseCode(
SourceMarkupLoader owner,
ManagedXmlReader xmlReader,
Parser.CodeType codeType)
{
Validate validate = null;
if (s_lexTable == null)
{
s_lexTable = new ParserLexTable();
s_yaccTable = new ParserYaccTable();
s_lex = new ParserLexClass(s_lexTable);
s_yacc = new ParserYaccClass(s_yaccTable, s_lex);
}
string prefix;
switch (codeType)
{
case CodeType.Methods:
prefix = "%%";
break;
case CodeType.InlineExpression:
prefix = "$$";
break;
default:
prefix = "@@";
break;
}
SSLexUnicodeBufferConsumer unicodeBufferConsumer = xmlReader.LexConsumerForValueWithPrefix(prefix);
s_lex.Reset(unicodeBufferConsumer);
s_yacc.Reset(owner);
s_parserActive = true;
s_yacc.parse();
if (!s_yacc.HasErrors)
{
validate = (Validate)s_yacc.treeRoot().Object;
if (MarkupSystem.TrackAdditionalMetadata)
validate.Metadata.OriginalValue = xmlReader.Value;
}
s_lex.Reset(null);
s_yacc.Reset(null);
s_parserActive = false;
return validate;
}
private static void ReportError(ManagedXmlReader xmlReader, string message) => ErrorManager.ReportError(xmlReader.LineNumber, xmlReader.LinePosition, message);
private static void ReportError(ManagedXmlReader xmlReader, string message, object param) => ErrorManager.ReportError(xmlReader.LineNumber, xmlReader.LinePosition, message, param);
private enum CodeType
{
ScriptBlock,
Methods,
InlineExpression,
}
private class ScriptBlock
{
public Validate ValidateValue;
public int Line;
public int Column;
public Parser.CodeType CodeType;
public ScriptBlock(int line, int column)
{
Line = line;
Column = column;
}
public ScriptBlock(int line, int column, Parser.CodeType codeType)
: this(line, column)
=> CodeType = codeType;
}
}
}