2021-03-31 16:42:58 -05:00
// 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 ;
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 ( NativeXmlReader xmlReader = new NativeXmlReader ( resource ))
{
try
{
string str1 = string . Empty ;
NativeXmlNodeType nodeType ;
while ( xmlReader . Read ( out nodeType ))
{
if ( parseResult . Root == null || parseStack . Count == 0 && nodeType == NativeXmlNodeType . EndElement )
{
if ( nodeType == NativeXmlNodeType . 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
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Unexpected attribute '{0}' on root tag" , name );
2021-03-31 16:42:58 -05:00
}
}
}
else
{
switch ( nodeType )
{
case NativeXmlNodeType . Element :
if ( flag )
{
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Script tag may not contain XML elements, found: '{0}'" , xmlReader . Name );
2021-03-31 16:42:58 -05:00
continue ;
}
bool isEmptyElement = xmlReader . IsEmptyElement ;
string prefix1 = xmlReader . Prefix ;
string localName = xmlReader . LocalName ;
if ( parseStack . Count % 2 == 0 )
{
if ( prefix1 == "" && localName == "Script" )
{
flag = true ;
2021-03-31 17:15:06 -05:00
parseStack . Push ( new Parser . ScriptBlock ( xmlReader . LineNumber , xmlReader . LinePosition ));
2021-03-31 16:42:58 -05:00
if ( xmlReader . ReadAttribute ())
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Script tag may not have XML attributes" );
2021-03-31 16:42:58 -05:00
}
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 )
{
2021-03-31 17:20:20 -05:00
ValidateObject objectFromString = CreateValidateObjectFromString ( owner , xmlReader );
2021-03-31 16:42:58 -05:00
ValidateProperty property = new ValidateProperty ( owner , xmlReader . LocalName , objectFromString , xmlReader . LineNumber , xmlReader . LinePosition );
objectTagValidator . AddProperty ( property );
}
else
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Property or Object tag may not have prefixed attributes: '{0}'" , xmlReader . Name );
2021-03-31 16:42:58 -05:00
}
2021-03-31 17:15:06 -05:00
parseStack . Push ( objectTagValidator );
2021-03-31 16:42:58 -05:00
if ( additionalMetadata && ! string . IsNullOrEmpty ( str1 ))
{
objectTagValidator . Metadata . Comments = str1 ;
str1 = string . Empty ;
}
}
}
else
{
if ( prefix1 != string . Empty )
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Property tag may not be prefixed: '{0}'" , xmlReader . Name );
2021-03-31 16:42:58 -05:00
if ( localName == "Methods" )
{
flag = true ;
2021-03-31 17:20:20 -05:00
parseStack . Push ( new Parser . ScriptBlock ( xmlReader . LineNumber , xmlReader . LinePosition , CodeType . Methods ));
2021-03-31 16:42:58 -05:00
if ( xmlReader . ReadAttribute ())
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Script tag may not have XML attributes" );
2021-03-31 16:42:58 -05:00
}
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
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Property or Object tag may not have prefixed attributes: '{0}'" , xmlReader . Name );
2021-03-31 16:42:58 -05:00
}
2021-03-31 17:15:06 -05:00
parseStack . Push ( validateProperty );
2021-03-31 16:42:58 -05:00
}
}
if ( isEmptyElement )
{
flag = false ;
2021-03-31 17:20:20 -05:00
HandleEndElement ( owner , parseResult , parseStack );
2021-03-31 16:42:58 -05:00
continue ;
}
continue ;
case NativeXmlNodeType . Text :
case NativeXmlNodeType . CDATA :
if ( parseStack . Count == 0 )
{
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Text/CDATA is not allowed under root tag ('{0}')" , xmlReader . Value . Trim ());
2021-03-31 16:42:58 -05:00
continue ;
}
switch ( parseStack . Peek ())
{
case ValidateProperty validateProperty :
if ( validateProperty . Value == null )
{
2021-03-31 17:20:20 -05:00
validateProperty . Value = CreateValidateObjectFromString ( owner , xmlReader );
2021-03-31 16:42:58 -05:00
continue ;
}
if ( validateProperty . Value is ValidateFromString )
{
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Property tag may only contain one Text/CDATA, found more text: '{0}'" , xmlReader . Value . Trim ());
2021-03-31 16:42:58 -05:00
continue ;
}
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Property tag already has objects, may not also add Text/CDATA: '{0}'" , xmlReader . Value . Trim ());
2021-03-31 16:42:58 -05:00
continue ;
case Parser . ScriptBlock scriptBlock :
if ( scriptBlock . ValidateValue == null )
{
2021-03-31 17:20:20 -05:00
scriptBlock . ValidateValue = ParseCode ( owner , xmlReader , scriptBlock . CodeType );
2021-03-31 16:42:58 -05:00
continue ;
}
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Script tag may only contain one Text/CDATA, found more text: '{0}'" , xmlReader . Value . Trim ());
2021-03-31 16:42:58 -05:00
continue ;
default :
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Object tag may not contain Text/CDATA: '{0}'" , xmlReader . Value . Trim ());
2021-03-31 16:42:58 -05:00
continue ;
}
case NativeXmlNodeType . Comment :
2021-03-31 17:15:06 -05:00
string str2 = null ;
2021-03-31 16:42:58 -05:00
if ( additionalMetadata )
{
str2 = xmlReader . Value ;
2021-03-31 17:15:06 -05:00
str1 = str1 + '\n' + str2 ;
2021-03-31 16:42:58 -05:00
}
if ( flag )
{
if ( str2 == null )
str2 = xmlReader . Value ;
2021-03-31 17:20:20 -05:00
ReportError ( xmlReader , "Script tag may not contain XML comments, found: '{0}'" , str2 . Trim ());
2021-03-31 16:42:58 -05:00
continue ;
}
continue ;
case NativeXmlNodeType . EndElement :
flag = false ;
2021-03-31 17:20:20 -05:00
HandleEndElement ( owner , parseResult , parseStack );
2021-03-31 16:42:58 -05:00
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 ;
2021-03-31 17:15:06 -05:00
ErrorManager . ReportError ( validateObjectTag . Line , validateObjectTag . Column , "Unexpected root element '{0}', must be <Class>, <UI> or <Alias>" , validateObjectTag . TypeIdentifier . TypeName );
2021-03-31 16:42:58 -05:00
break ;
}
2021-03-31 17:15:06 -05:00
ErrorManager . ReportError ( scriptBlock . Line , scriptBlock . Column , "Unexpected root element '{0}', must be <Class>, <UI> or <Alias>" , "Script" );
2021-03-31 16:42:58 -05:00
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 ,
NativeXmlReader xmlReader )
{
if ( xmlReader . IsInlineExpression )
2021-03-31 17:20:20 -05:00
return ( ValidateObject ) ParseCode ( owner , xmlReader , CodeType . InlineExpression );
2021-03-31 16:42:58 -05:00
string fromString = xmlReader . Value ;
bool expandEscapes = true ;
if ( fromString . Length > 0 && fromString [ 0 ] == '@' )
{
fromString = fromString . Substring ( 1 );
expandEscapes = false ;
}
2021-03-31 17:15:06 -05:00
return new ValidateFromString ( owner , fromString , expandEscapes , xmlReader . LineNumber , xmlReader . LinePosition );
2021-03-31 16:42:58 -05:00
}
private static Validate ParseCode (
SourceMarkupLoader owner ,
NativeXmlReader xmlReader ,
Parser . CodeType codeType )
{
2021-03-31 17:15:06 -05:00
Validate validate = null ;
2021-03-31 17:20:20 -05:00
if ( s_lexTable == null )
2021-03-31 16:42:58 -05:00
{
2021-03-31 17:20:20 -05:00
s_lexTable = new ParserLexTable ();
s_yaccTable = new ParserYaccTable ();
s_lex = new ParserLexClass ( s_lexTable );
s_yacc = new ParserYaccClass ( s_yaccTable , s_lex );
2021-03-31 16:42:58 -05:00
}
string prefix ;
switch ( codeType )
{
2021-03-31 17:20:20 -05:00
case CodeType . Methods :
2021-03-31 16:42:58 -05:00
prefix = "%%" ;
break ;
2021-03-31 17:20:20 -05:00
case CodeType . InlineExpression :
2021-03-31 16:42:58 -05:00
prefix = "$$" ;
break ;
default :
prefix = "@@" ;
break ;
}
SSLexUnicodeBufferConsumer unicodeBufferConsumer = xmlReader . LexConsumerForValueWithPrefix ( prefix );
2021-03-31 17:20:20 -05:00
s_lex . Reset ( unicodeBufferConsumer );
s_yacc . Reset ( owner );
s_parserActive = true ;
s_yacc . parse ();
if (! s_yacc . HasErrors )
2021-03-31 16:42:58 -05:00
{
2021-03-31 17:20:20 -05:00
validate = ( Validate ) s_yacc . treeRoot (). Object ;
2021-03-31 16:42:58 -05:00
if ( MarkupSystem . TrackAdditionalMetadata )
2021-03-31 17:15:06 -05:00
validate . Metadata . OriginalValue = xmlReader . Value ;
2021-03-31 16:42:58 -05:00
}
2021-03-31 17:20:20 -05:00
s_lex . Reset ( null );
s_yacc . Reset ( null );
s_parserActive = false ;
2021-03-31 16:42:58 -05:00
return validate ;
}
private static void ReportError ( NativeXmlReader xmlReader , string message ) => ErrorManager . ReportError ( xmlReader . LineNumber , xmlReader . LinePosition , message );
private static void ReportError ( NativeXmlReader 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 )
{
2021-04-02 19:10:51 -05:00
Line = line ;
Column = column ;
2021-03-31 16:42:58 -05:00
}
public ScriptBlock ( int line , int column , Parser . CodeType codeType )
: this ( line , column )
2021-04-02 19:10:51 -05:00
=> CodeType = codeType ;
2021-03-31 16:42:58 -05:00
}
}
}