From bc77be79d242e006ff96818db3a069c86255ecf6 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 16 Oct 2022 20:17:48 -0400 Subject: [PATCH] JSON parser checkpoint --- spec/json_types.d | 63 +++++++++++++++++ spec/propane_spec.rb | 142 +++++++++++++++++++++++++++++++++++++++ spec/test_parsing_json.d | 14 ++++ 3 files changed, 219 insertions(+) create mode 100644 spec/json_types.d create mode 100644 spec/test_parsing_json.d diff --git a/spec/json_types.d b/spec/json_types.d new file mode 100644 index 0000000..a8d455b --- /dev/null +++ b/spec/json_types.d @@ -0,0 +1,63 @@ +class JSONValue +{ +} + +class JSONObject : JSONValue +{ + JSONValue[string] value; + + this() + { + } + + this(JSONValue[string] value) + { + this.value = value; + } +} + +class JSONArray : JSONValue +{ + JSONValue[] value; + + this() + { + } + + this(JSONValue[] value) + { + this.value = value; + } +} + +class JSONNumber : JSONValue +{ + double value; + + this(double value) + { + this.value = value; + } +} + +class JSONString : JSONValue +{ + string value; + + this(string value) + { + this.value = value; + } +} + +class JSONTrue : JSONValue +{ +} + +class JSONFalse : JSONValue +{ +} + +class JSONNull : JSONValue +{ +} diff --git a/spec/propane_spec.rb b/spec/propane_spec.rb index 22eec6e..0aeed0b 100644 --- a/spec/propane_spec.rb +++ b/spec/propane_spec.rb @@ -334,4 +334,146 @@ EOF expect(results.stderr).to eq "" expect(results.status).to eq 0 end + + it "allows creating a JSON parser" do + write_grammar <> + +ptype JSONValue; +ptype array = JSONValue[]; +ptype dict = JSONValue[string]; +ptype string = string; + +drop /\\s+/; +token lbrace /\\{/; +token rbrace /\\}/; +token lbracket /\\[/; +token rbracket /\\]/; +token comma /,/; +token colon /:/; +token number /-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][-+]?[0-9]+)?/ << + bool negative; + bool in_fraction; + bool in_exponent; + double exponent; + foreach (c; match) + { + if (c == '-') + { + negative = true; + } + } + double n = 1.0; + $$ = new JSONNumber(n); +>> +token true << + $$ = new JSONTrue(); +>> +token false << + $$ = new JSONFalse(); +>> +token null << + $$ = new JSONNull(); +>> +/"/ << + $mode(string); + string_value = ""; +>> +string: token string (string) /"/ << + $$ = string_value; + $mode(default); +>> +string: /\\\\"/ << + string_value ~= "\\""; +>> +string: /\\\\\\\\/ << + string_value ~= "\\\\"; +>> +string: /\\\\\\// << + string_value ~= "/"; +>> +string: /\\\\b/ << + string_value ~= "\\b"; +>> +string: /\\\\f/ << + string_value ~= "\\f"; +>> +string: /\\\\n/ << + string_value ~= "\\n"; +>> +string: /\\\\r/ << + string_value ~= "\\r"; +>> +string: /\\\\t/ << + string_value ~= "\\t"; +>> +string: /\\\\u[0-9a-fA-F]{4}/ << + /* Not actually going to encode the code point for this example... */ + string_value ~= "{" ~ match[2..6] ~ "}"; +>> +string: /[^\\\\]/ << + string_value ~= match; +>> +Start -> Value << + $$ = $1; +>> +Value -> string << + $$ = new JSONString($1); +>> +Value -> number << + $$ = $1; +>> +Value -> Object << + $$ = $1; +>> +Value -> Array << + $$ = $1; +>> +Value -> true << + $$ = $1; +>> +Value -> false << + $$ = $1; +>> +Value -> null << + $$ = $1; +>> +Object -> lbrace rbrace << + $$ = new JSONObject(); +>> +Object -> lbrace KeyValues rbrace << + $$ = new JSONObject($2); +>> +KeyValues (dict) -> KeyValue << + $$ = $1; +>> +KeyValues -> KeyValues comma KeyValue << + foreach (key, value; $3) + { + $1[key] = value; + } + $$ = $1; +>> +KeyValue (dict) -> string colon Value << + $$ = [$1: $3]; +>> +Array -> lbracket rbracket << + $$ = new JSONArray(); +>> +Array -> lbracket Values rbracket << + $$ = new JSONArray($2); +>> +Values (array) -> Value << + $$ = [$1]; +>> +Values -> Values comma Value << + $$ = $1 ~ [$3]; +>> +EOF + build_parser + compile("spec/test_parsing_json.d", "spec/json_types.d") + end end diff --git a/spec/test_parsing_json.d b/spec/test_parsing_json.d new file mode 100644 index 0000000..3312333 --- /dev/null +++ b/spec/test_parsing_json.d @@ -0,0 +1,14 @@ +import testparser; +import std.stdio; + +int main() +{ + return 0; +} + +unittest +{ + string input = ``; + auto parser = new Testparser.Parser(input); + assert(parser.parse() == true); +}