Skip to content

Instantly share code, notes, and snippets.

@takeshik
Created December 21, 2012 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takeshik/4353249 to your computer and use it in GitHub Desktop.
Save takeshik/4353249 to your computer and use it in GitHub Desktop.
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