Created
December 21, 2012 14:50
-
-
Save takeshik/4353249 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TypeName | |
{ | |
public String Namespace { get; set; } | |
public String[] HierarchicalNames { get; set; } | |
public override String ToString() | |
{ | |
return String.Join("+", this.HierarchicalNames); | |
} | |
} | |
public class TypeDescriptor | |
{ | |
public TypeName TypeName { get; set; } | |
public TypeDescriptor[] TypeArguments { get; set; } | |
public String[] Suffixes { get; set; } | |
public AssemblyName Assembly { get; set; } | |
public override String ToString() | |
{ | |
return this.TypeName + (this.TypeArguments.Any() | |
? "<" + String.Join(", ", this.TypeArguments.SelectAll(t => t.ToString())) + ">" | |
: "" | |
) + String.Concat(this.Suffixes); | |
} | |
} | |
void Main() | |
{ | |
var comma = ','.Satisfy() | |
.Pipe(' '.Satisfy().Many(), (l, r) => r.StartWith(l)); | |
var equal = ','.Satisfy() | |
.Pipe(' '.Satisfy().Many(), (l, r) => r.StartWith(l)); | |
var assemblyName = Combinator.Choice( | |
Chars.OneOf('`', '[', ']', '+', ',').Let(ds => ds | |
.Not() | |
.Right('\\'.Satisfy().Right(ds)) | |
.Or(Chars.NoneOf('`', '[', ']', '+', ',')) | |
.Many() | |
), | |
Combinator.Sequence( | |
Chars.Sequence("Version"), | |
equal, | |
Chars.Digit() | |
.Many() | |
.SepBy(3, '.'.Satisfy()) | |
.Select(cs => cs.SelectMany(_ => _)) | |
).Select(_ => _.SelectMany(cs => cs)), | |
Combinator.Sequence( | |
Chars.Sequence("Culture"), | |
equal, | |
Chars.Letter() | |
.Many() | |
).Select(_ => _.SelectMany(cs => cs)), | |
Combinator.Sequence( | |
Chars.Sequence("PublicKeyToken"), | |
equal, | |
Chars.Hex() | |
.Many(16) | |
.Or(Chars.Sequence("null")) | |
).Select(_ => _.SelectMany(cs => cs)) | |
) | |
.SepBy(comma) | |
.Select(fs => new String(fs | |
.SelectMany(cs => cs.EndWith(',')) | |
.ToArray() | |
).If(String.IsNullOrWhiteSpace, | |
_ => new AssemblyName(), | |
s => new AssemblyName(s)) | |
); | |
Parser<Char, TypeDescriptor> typeNameRef = null; | |
var typeName = new Lazy<Parser<Char, TypeDescriptor>>(() => stream => typeNameRef(stream)); | |
typeNameRef = Chars.OneOf('`', '[', ']', '+', '.', ',', '*', '&').Let(ds => ds | |
.Not() | |
.Right('\\'.Satisfy().Right(ds)) | |
.Or(Chars.NoneOf('`', '[', ']', '+', '.', ',', '*', '&')) | |
.Many() | |
).Let(name => | |
Combinator.Sequence( | |
name, | |
Chars.Sequence(".") | |
) | |
.Select(_ => new String(_.SelectMany(cs => cs).SkipLast(1).ToArray())) | |
.Many() | |
.Pipe( | |
name | |
.Select(cs => new String(cs.ToArray())), | |
Combinator.Sequence( | |
Chars.Sequence("+"), | |
name | |
) | |
.Select(_ => new String(_.SelectMany(cs => cs).Skip(1).ToArray())) | |
.Many(), | |
(nss, n, ins) => new TypeName() | |
{ | |
Namespace = String.Join(".", nss), | |
HierarchicalNames = ins.StartWith(n).ToArray(), | |
} | |
) | |
).Pipe( | |
'`'.Satisfy() | |
.Pipe( | |
Chars.Digit() | |
.Many(), | |
(_, ds) => Int32.Parse(new String(ds.ToArray())) | |
) | |
.Maybe() | |
.Select(_ => _.Otherwise(() => 0)), | |
typeName.Value | |
.Between('['.Satisfy(), ']'.Satisfy()) | |
.SepBy(comma) | |
.Between('['.Satisfy(), ']'.Satisfy()) | |
.Maybe() | |
.Select(_ => _.Otherwise(() => new TypeDescriptor[0])), | |
Combinator.Choice( | |
Chars.Sequence("*"), | |
Chars.Sequence("&"), | |
Chars.Sequence("*") | |
.Or(Chars.Sequence(",")) | |
.Many() | |
.Between('['.Satisfy(), ']'.Satisfy()) | |
.Select(_ => _ | |
.SelectMany(cs => cs) | |
.StartWith('[') | |
.EndWith(']') | |
) | |
) | |
.Many() | |
.Maybe(), | |
comma.Pipe(assemblyName, (_, an) => an) | |
.Maybe(), | |
(tn, n, tas, ss, an) => new TypeDescriptor() | |
{ | |
TypeName = tn, | |
TypeArguments = tas.ToArray(), | |
Suffixes = ss.Select(_ => _.Select(cs => new String(cs.ToArray())).ToArray()).Otherwise(() => new String[0]), | |
Assembly = an.Otherwise(() => null), | |
} | |
); | |
ErrorMessage err; | |
TypeDescriptor ret; | |
typeNameRef( | |
"System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Func`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]][][,]&".AsStream() | |
).TryGetValue(out ret, out err); | |
ret.Dump(); // Dictionary<String, Func<Int32, Int32>> | |
} | |
/* | |
{ | |
"TypeName": { | |
"Namespace": "System.Collections.Generic", | |
"HierarchicalNames": [ | |
"Dictionary" | |
] | |
}, | |
"TypeArguments": [ | |
{ | |
"TypeName": { | |
"Namespace": "System", | |
"HierarchicalNames": [ | |
"String" | |
] | |
}, | |
"TypeArguments": [], | |
"Suffixes": [ | |
"[]" | |
], | |
"Assembly": "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" | |
}, | |
{ | |
"TypeName": { | |
"Namespace": "System", | |
"HierarchicalNames": [ | |
"Func" | |
] | |
}, | |
"TypeArguments": [ | |
{ | |
"TypeName": { | |
"Namespace": "System", | |
"HierarchicalNames": [ | |
"Int32" | |
] | |
}, | |
"TypeArguments": [], | |
"Suffixes": [], | |
"Assembly": "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" | |
}, | |
{ | |
"TypeName": { | |
"Namespace": "System", | |
"HierarchicalNames": [ | |
"Int32" | |
] | |
}, | |
"TypeArguments": [], | |
"Suffixes": [], | |
"Assembly": "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" | |
} | |
], | |
"Suffixes": [], | |
"Assembly": "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" | |
} | |
], | |
"Suffixes": [ | |
"[]", | |
"[,]", | |
"&" | |
], | |
"Assembly": null | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment