Skip to content

Instantly share code, notes, and snippets.

@kokudori
Last active March 7, 2016 03:34
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 kokudori/5252810 to your computer and use it in GitHub Desktop.
Save kokudori/5252810 to your computer and use it in GitHub Desktop.
start = Object
value = dynamic
namespace = JsonParser
Object := UnVisibles '{' UnVisibles ObjectWithKeys UnVisibles '}' UnVisibles
`;` `expected = "object"`
ObjectWithKey := Identifier Spaces ':' Spaces (Literal / InnerObject)
`value = ToPair(results)`
ObjectWithKey := String Spaces ':' Spaces (Literal / InnerObject)
`value = ToPairByString(results)`
ObjectWithKeys := ObjectWithKey (',' UnVisibles ObjectWithKey)* `AddObject(results)`
InnerObject := UnVisibles '{' UnVisibles ObjectWithKey (',' UnVisibles ObjectWithKey)* UnVisibles '}' UnVisibles
`value = ToObject(results)`
Identifier := [a-zA-Z_] [0-9a-zA-Z]*
`;` `expected = "identifier"`
Literal := String / Number / Boolean / Undefined / Null;
Null := 'null'
`value = null` `expected = "null"`
Undefined := 'undefined'
`value = null` `expected = "undefined"`
Boolean := 'true' / 'false'
`value = ToBoolean(results)` `expected = "boolean"`
Number := '-'? [0-9]+ ('.' [0-9]+)?
`value = ToNumber(results)` `expected = "number"`
String := (["] ([^\r\n"])* ["]) / (['] ([^\r\n'])* ['])
`value = ToString(results)` `expected = "string"`
UnVisibles := Spaces NewLines Spaces;
Spaces := Space*;
Space := [ \t] `;` `expected = "whitespace"`
NewLines := NewLine*;
NewLine := [\r\n] `;` `expected = "newline"`
using System;
using System.Collections.Generic;
using System.Linq;
namespace JsonParser
{
static class Helper
{
internal static void Each<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
}
}
}
class Context
{
public Dictionary<string, dynamic> Root { get; private set; }
public Context()
{
Root = new Dictionary<string,dynamic>();
}
public void AddObject(string name, dynamic value)
{
Root.Add(name, value);
}
}
partial class Parser
{
Context context = new Context();
public Dictionary<string, dynamic> Root { get { return context.Root; } }
double ToNumber(IEnumerable<Result> results)
{
return Double.Parse(String.Join("", results.Select(x => x.Text)));
}
bool ToBoolean(IEnumerable<Result> results)
{
return Boolean.Parse(results.First().Text);
}
string ToString(IEnumerable<Result> results)
{
return String.Join("",
results
.Skip(1)
.TakeWhile(x => x.Text != results.Last().Text)
.Select(x => x.Text)
);
}
KeyValuePair<string, dynamic> ToPair(IEnumerable<Result> results)
{
if (results.All(x => x.Value == null))
return new KeyValuePair<string, dynamic>();
var value = results.Where(x => x.Value != null).Single().Value;
var name = results.First().Text;
return new KeyValuePair<string, dynamic>(name, value);
}
KeyValuePair<string, dynamic> ToPairByString(IEnumerable<Result> results)
{
if (results.All(x => x.Value == null))
return new KeyValuePair<string, dynamic>();
var value = results.Where(x => x.Value != null).Skip(1).Single().Value;
var name = results.First().Text.Substring(1, results.First().Text.Count() -2);
return new KeyValuePair<string, dynamic>(name, value);
}
Dictionary<string, dynamic> ToObject(IEnumerable<Result> results)
{
var jsonObject = new Dictionary<string, dynamic>();
results
.Select(x => x.Value)
.OfType<KeyValuePair<string, dynamic>>()
.Each(x => jsonObject.Add(x.Key, x.Value));
return jsonObject;
}
void AddObject(IEnumerable<Result> results)
{
results
.Select(x => x.Value)
.OfType<KeyValuePair<string, dynamic>>()
.Each(x => context.AddObject(x.Key, x.Value));
}
}
class Program
{
static void Main(string[] args)
{
var input =
@"
{
hoge: 100,
piyo: {
inner: 'hogehoge',
inner2: 23.45
},
fuga: -300,
'abc': 100,
""bca"": ""aaaa"",
'hoge piyo': 'fuga bar'
}
";
var parser = new Parser();
parser.Parse(input);
Console.WriteLine("input");
Console.WriteLine(input);
Console.WriteLine("Root['hoge'] == {0}", parser.Root["hoge"]);
Console.WriteLine("Root['hoge'].GetType() == {0}", parser.Root["hoge"].GetType());
Console.WriteLine("Root['piyo'].Count == {0}", parser.Root["piyo"].Count);
Console.WriteLine("Root['piyo']['inner'] == {0}", parser.Root["piyo"]["inner"]);
Console.WriteLine("Root['piyo']['inner'].GetType() == {0}", parser.Root["piyo"]["inner"].GetType());
Console.WriteLine("Root['piyo']['inner2'] == {0}", parser.Root["piyo"]["inner2"]);
Console.WriteLine("Root['piyo']['inner2'].GetType() == {0}", parser.Root["piyo"]["inner2"].GetType());
Console.WriteLine("Root['fuga'] == {0}", parser.Root["fuga"]);
Console.WriteLine("Root['fuga'].GetType() == {0}", parser.Root["fuga"].GetType());
Console.WriteLine("Root['abc'] == {0}", parser.Root["abc"]);
Console.WriteLine("Root['abc'].GetType() == {0}", parser.Root["abc"].GetType());
Console.WriteLine("Root['bca'] == {0}", parser.Root["bca"]);
Console.WriteLine("Root['bca'].GetType() == {0}", parser.Root["bca"].GetType());
Console.WriteLine("Root['hoge piyo'] == {0}", parser.Root["hoge piyo"]);
Console.WriteLine("Root['hoge piyo'].GetType() == {0}", parser.Root["hoge piyo"].GetType());
}
}
}
@kokudori
Copy link
Author

peg-sharp.exe JsonParser.peg でJsonParser.csが生成されます。
peg-shaprについてはこちらを御覧ください。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment