This repository has been archived by the owner on Jun 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathMarkupExtensionParser.cs
105 lines (81 loc) · 6.04 KB
/
MarkupExtensionParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
namespace OmniXaml.InlineParsers.Extensions
{
using System.Globalization;
using System.Linq;
using Sprache;
public static class MarkupExtensionParser
{
private const char Quote = '\'';
private const char OpenCurly = '{';
private const char CloseCurly = '}';
private const char Comma = ',';
private const char Colon = ':';
private const char EqualSign = '=';
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> IdentifierChar = Parse
.LetterOrDigit
.Or(ConnectingCharacter)
.Or(CombiningCharacter)
.Or(FormattingCharacter);
public static readonly Parser<char> IdentifierFirst = Parse.Letter.Or(Parse.Char('_'));
private static readonly Parser<TreeNode> QuotedValue =
from firstQuote in Parse.Char(Quote)
from identifier in Parse.CharExcept(new[] {Quote, OpenCurly, CloseCurly}).Many()
from secondQuote in Parse.Char(Quote)
select new StringNode(new string(identifier.ToArray()));
public static readonly Parser<string> Identifier =
from first in IdentifierFirst.Once().Text()
from rest in IdentifierChar.Many().Text()
select first + rest;
private static readonly Parser<TreeNode> DirectValue =
from value in ValidChars.Many()
select new StringNode(new string(value.ToArray()));
private static Parser<char> ValidChars => Parse.AnyChar.Except(Parse.Chars(Quote, OpenCurly, CloseCurly, EqualSign, Comma).Or(Parse.WhiteSpace));
private static readonly Parser<TreeNode> StringValueNode = QuotedValue.Or(DirectValue);
public static readonly Parser<AssignmentNode> Assignment = from prop in Identifier
from trailing in Parse.WhiteSpace.Many()
from eqSign in Parse.Char(EqualSign)
from trailing2 in Parse.WhiteSpace.Many()
from value in AssignmentSource
from trailing3 in Parse.WhiteSpace.Many()
select new AssignmentNode(prop, value);
public static readonly Parser<Option> Positional = from value in ValidChars.Many()
select new PositionalOption(new string(value.ToArray()));
private static readonly Parser<Option> Attribute = from identifier in Assignment
select new PropertyOption(identifier.Property, identifier.Value);
public static readonly Parser<OptionsCollection> Options = from options in Attribute.Or(Positional).DelimitedBy(Parse.Char(Comma).Token())
select new OptionsCollection(options);
private static readonly Parser<MarkupExtensionNode> SimpleMarkupExtension = from openCurly in Parse.Char(OpenCurly)
from identifier in XamlTypeIdentifier
from closeCurly in Parse.Char(CloseCurly)
select new MarkupExtensionNode(identifier);
private static readonly Parser<MarkupExtensionNode> MarkupExtensionWithOptions = from openCurly in Parse.Char(OpenCurly)
from identifier in XamlTypeIdentifier
from space in Parse.WhiteSpace.AtLeastOnce()
from options in Options.Once()
from closeCurly in Parse.Char(CloseCurly)
select new MarkupExtensionNode(identifier, options.First());
private static readonly Parser<IdentifierNode> IdentifierWithPrefix = from prefix in Identifier
from colon in Parse.Char(Colon)
from typeName in Identifier
select new IdentifierNode(prefix, typeName);
private static readonly Parser<IdentifierNode> IdentifierWithoutPrefix = from id in Identifier
select new IdentifierNode(id);
private static readonly Parser<IdentifierNode> XamlTypeIdentifier = IdentifierWithPrefix.Or(IdentifierWithoutPrefix);
public static readonly Parser<MarkupExtensionNode> MarkupExtension = MarkupExtensionWithOptions.Or(SimpleMarkupExtension);
private static readonly Parser<TreeNode> AssignmentSource = MarkupExtension.Or(StringValueNode);
}
}