|
|
@@ -0,0 +1,176 @@
|
|
|
+// Copyright (c) The Perspex Project. All rights reserved.
|
|
|
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
|
+
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Globalization;
|
|
|
+using System.Linq;
|
|
|
+using Perspex.Styling;
|
|
|
+using Sprache;
|
|
|
+
|
|
|
+namespace Perspex.Markup.Xaml.Parsers
|
|
|
+{
|
|
|
+ internal class SelectorGrammar
|
|
|
+ {
|
|
|
+ public static readonly Parser<char> CombiningCharacter = Parse.Char(
|
|
|
+ c =>
|
|
|
+ {
|
|
|
+ var cat = CharUnicodeInfo.GetUnicodeCategory(c);
|
|
|
+ return cat == UnicodeCategory.NonSpacingMark ||
|
|
|
+ cat == UnicodeCategory.SpacingCombiningMark;
|
|
|
+ },
|
|
|
+ "Connecting Character");
|
|
|
+
|
|
|
+ public static readonly Parser<char> ConnectingCharacter = Parse.Char(
|
|
|
+ c => CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.ConnectorPunctuation,
|
|
|
+ "Connecting Character");
|
|
|
+
|
|
|
+ public static readonly Parser<char> FormattingCharacter = Parse.Char(
|
|
|
+ c => CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Format,
|
|
|
+ "Connecting Character");
|
|
|
+
|
|
|
+ public static readonly Parser<char> IdentifierStart = Parse.Letter.Or(Parse.Char('_'));
|
|
|
+
|
|
|
+ public static readonly Parser<char> IdentifierChar = Parse
|
|
|
+ .LetterOrDigit
|
|
|
+ .Or(ConnectingCharacter)
|
|
|
+ .Or(CombiningCharacter)
|
|
|
+ .Or(FormattingCharacter);
|
|
|
+
|
|
|
+ public static readonly Parser<string> Identifier =
|
|
|
+ from start in IdentifierStart.Once().Text()
|
|
|
+ from @char in IdentifierChar.Many().Text()
|
|
|
+ select start + @char;
|
|
|
+
|
|
|
+ public static readonly Parser<OfTypeSyntax> OfType =
|
|
|
+ from identifier in Identifier select new OfTypeSyntax { TypeName = identifier };
|
|
|
+
|
|
|
+ public static readonly Parser<NameSyntax> Name =
|
|
|
+ from hash in Parse.Char('#')
|
|
|
+ from identifier in Identifier
|
|
|
+ select new NameSyntax { Name = identifier };
|
|
|
+
|
|
|
+ public static readonly Parser<char> ClassStart = Parse.Char('_').Or(Parse.Letter);
|
|
|
+
|
|
|
+ public static readonly Parser<char> ClassChar = ClassStart.Or(Parse.Numeric);
|
|
|
+
|
|
|
+ public static readonly Parser<string> ClassIdentifier =
|
|
|
+ from start in ClassStart.Once().Text()
|
|
|
+ from @char in ClassChar.Many().Text()
|
|
|
+ select start + @char;
|
|
|
+
|
|
|
+ public static readonly Parser<ClassSyntax> StandardClass =
|
|
|
+ from dot in Parse.Char('.').Once()
|
|
|
+ from identifier in ClassIdentifier
|
|
|
+ select new ClassSyntax { Class = identifier };
|
|
|
+
|
|
|
+ public static readonly Parser<ClassSyntax> Pseduoclass =
|
|
|
+ from colon in Parse.Char(':').Once()
|
|
|
+ from identifier in ClassIdentifier
|
|
|
+ select new ClassSyntax { Class = ':' + identifier };
|
|
|
+
|
|
|
+ public static readonly Parser<ClassSyntax> Class = StandardClass.Or(Pseduoclass);
|
|
|
+
|
|
|
+ public static readonly Parser<PropertySyntax> Property =
|
|
|
+ from open in Parse.Char('[').Once()
|
|
|
+ from identifier in Identifier
|
|
|
+ from eq in Parse.Char('=').Once()
|
|
|
+ from value in Parse.CharExcept(']').Many().Text()
|
|
|
+ from close in Parse.Char(']').Once()
|
|
|
+ select new PropertySyntax { Property = identifier, Value = value };
|
|
|
+
|
|
|
+ public static readonly Parser<ChildSyntax> Child = Parse.Char('<').Token().Return(new ChildSyntax());
|
|
|
+
|
|
|
+ public static readonly Parser<DescendentSyntax> Descendent =
|
|
|
+ from child in Parse.WhiteSpace.Many()
|
|
|
+ select new DescendentSyntax();
|
|
|
+
|
|
|
+ public static readonly Parser<TemplateSyntax> Template =
|
|
|
+ from template in Parse.String("/template/").Token()
|
|
|
+ select new TemplateSyntax();
|
|
|
+
|
|
|
+ //public static readonly
|
|
|
+
|
|
|
+ public static readonly Parser<ISyntax> SingleSelector =
|
|
|
+ OfType
|
|
|
+ .Or<ISyntax>(Name)
|
|
|
+ .Or<ISyntax>(Class)
|
|
|
+ .Or<ISyntax>(Property)
|
|
|
+ .Or<ISyntax>(Child)
|
|
|
+ .Or<ISyntax>(Template)
|
|
|
+ .Or<ISyntax>(Descendent);
|
|
|
+
|
|
|
+ public static readonly Parser<IEnumerable<ISyntax>> Selector = SingleSelector.Many();
|
|
|
+
|
|
|
+ public interface ISyntax
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public class OfTypeSyntax : ISyntax
|
|
|
+ {
|
|
|
+ public string TypeName { get; set; }
|
|
|
+
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is OfTypeSyntax && ((OfTypeSyntax)obj).TypeName == TypeName;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ClassSyntax : ISyntax
|
|
|
+ {
|
|
|
+ public string Class { get; set; }
|
|
|
+
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is ClassSyntax && ((ClassSyntax)obj).Class == Class;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class NameSyntax : ISyntax
|
|
|
+ {
|
|
|
+ public string Name { get; set; }
|
|
|
+
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is NameSyntax && ((NameSyntax)obj).Name == Name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class PropertySyntax : ISyntax
|
|
|
+ {
|
|
|
+ public string Property { get; set; }
|
|
|
+
|
|
|
+ public string Value { get; set; }
|
|
|
+
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is PropertySyntax &&
|
|
|
+ ((PropertySyntax)obj).Property == Property &&
|
|
|
+ ((PropertySyntax)obj).Value == Value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ChildSyntax : ISyntax
|
|
|
+ {
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is ChildSyntax;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class DescendentSyntax : ISyntax
|
|
|
+ {
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is DescendentSyntax;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class TemplateSyntax : ISyntax
|
|
|
+ {
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ return obj is TemplateSyntax;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|