Skip to content

Instantly share code, notes, and snippets.

@takahisa
Created February 18, 2012 09:11
Show Gist options
  • Save takahisa/1858379 to your computer and use it in GitHub Desktop.
Save takahisa/1858379 to your computer and use it in GitHub Desktop.
YacqReader(Parseq版)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XSpect.Yacq.Expressions;
using Parseq;
using Parseq.Combinators;
namespace XSpect.Yacq.LanguageServices
{
public static class YacqReader {
public static Parser<Char, YacqExpression[]> YacqParser(){
return Combinator.Choice(Text(), Number(), Identifier(), List(), Lambda())
.Between(Spaces(), Spaces()).Many();
}
private static Parser<Char, Char[]> Spaces(){
return Chars.Space().Many();
}
private static Parser<Char, YacqExpression> Lambda(){
return (from x in '{'.Match().Left(Spaces())
from y in Combinator.Choice(Text(), Number(), Identifier()).Between(Spaces(), Spaces()).Many()
from z in '}'.Match().Left(Spaces())
select YacqExpression.LambdaList(y)).Select(_ => (YacqExpression)_);
}
private static Parser<Char, YacqExpression> List(){
return (from x in '('.Match().Left(Spaces())
from y in Combinator.Choice(Text(), Number(), Identifier()).Between(Spaces(), Spaces()).Many()
from z in ')'.Match().Left(Spaces())
select YacqExpression.List(y)).Select(_ => (YacqExpression)_);
}
private static Parser<Char, YacqExpression> Text(){
return (from a in Chars.OneOf('\"', '\'', '`')
from b in Chars.Any().While(Combinator.Choice(
'\\'.Match().Right(a.Match()).And().Ignore(),
a.Match().Not()))
from c in a.Match()
select YacqExpression.Text(new String(b))).Select(_ => (YacqExpression)_);
}
private static Parser<Char, YacqExpression> Number(){
return (from x in NumberPrefix().Maybe()
from y in
Combinator.Choice(
from a in Combinator.Sequence('0'.Match(), Chars.OneOf('x', 'X'))
from b in Hex().Many(1)
select new StringBuilder().Append(a).Append(b).ToString(),
from a in Combinator.Sequence('0'.Match(), Chars.OneOf('o', 'O'))
from b in Oct().Many(1)
select new StringBuilder().Append(a).Append(b).ToString(),
from a in Combinator.Sequence('0'.Match(), Chars.OneOf('b', 'B'))
from b in Bin().Many(1)
select new StringBuilder().Append(a).Append(b).ToString(),
from a in Digit().Many(1)
from b in '.'.Match()
from c in Digit().Many(1)
from d in
(from e in Chars.OneOf('e', 'E')
from f in Chars.OneOf('+', '-').Maybe()
from g in Digit().Many(1)
select new StringBuilder().Append(e).Append(f.Otherwise(() => '+')).Append(g).ToString()).Maybe()
select new StringBuilder().Append(a).Append('.').Append(c).Append(d.Otherwise(() => String.Empty)).ToString())
from z in NumberSuffix().Maybe()
select YacqExpression.Number(x.Otherwise(() => String.Empty) + y + z.Otherwise(() => String.Empty))).Select(_ => (YacqExpression)_);
}
private static Parser<Char, YacqExpression> Identifier(){
return (Combinator.Choice(
from x in '.'.Match().Many(1)
from y in Chars.OneOf(' ', '\r', '\t')
select YacqExpression.Identifier(new String(x)),
from x in ':'.Match().Many(1)
from y in Chars.OneOf(' ', '\r', '\t')
select YacqExpression.Identifier(new String(x)),
from x in Chars.OneOf('+', '-')
from y in Combinator.Sequence(Punctuation().Not(), Chars.Digit().Not())
from z in Chars.Any().While(Punctuation().Not())
select YacqExpression.Identifier(new StringBuilder().Append(x).Append(z).ToString()),
from x in Combinator.Sequence(Punctuation().Not(), Chars.Digit().Not())
from y in Chars.Any().While(Punctuation().Not())
select YacqExpression.Identifier(new String(y)))).Select(_ => (YacqExpression)_);
}
private static Parser<Char, Char> Punctuation(){
return Chars.OneOf(';', '\'', '\"', '`', '(', ')', '[', ']', '{', '}', ',', '.', ':');
}
private static Parser<Char, Char> Digit(){
return Chars.Digit().Or('_'.Match().Right(Digit()));
}
private static Parser<Char, Char> Bin(){
return Chars.OneOf('0', '1').Or('_'.Match().Right(Bin()));
}
private static Parser<Char, Char> Oct(){
return Chars.Oct().Or('_'.Match().Right(Oct()));
}
private static Parser<Char, Char> Hex(){
return Chars.Hex().Or('_'.Match().Right(Hex()));
}
private static Parser<Char, String> NumberPrefix(){
return Chars.OneOf('+', '-').Select(_ => _.ToString());
}
private static Parser<Char, String> NumberSuffix(){
return Combinator.Sequence(Chars.OneOf('u','U'),Chars.OneOf('l','L')).Select(_ => new String(_))
.Or(Chars.OneOf('f', 'F', 'd', 'D', 'm', 'M', 'u', 'U', 'l', 'L').Select(_ => _.ToString()));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment