Compare commits
3 Commits
c6ea4f83c2
...
dbc5560aec
Author | SHA1 | Date | |
---|---|---|---|
dbc5560aec | |||
62451f3a92 | |||
2e48921bb1 |
@ -191,7 +191,7 @@ class Propane
|
||||
end
|
||||
code = code.gsub(/\$(\d+)/) do |match|
|
||||
index = $1.to_i
|
||||
"statevalues[$-1-n_states+#{index}].pvalue.v_#{rule.ptypename}"
|
||||
"statevalues[$-1-n_states+#{index}].pvalue.v_#{rule.components[index - 1].ptypename}"
|
||||
end
|
||||
else
|
||||
code = code.gsub(/\$\$/) do |match|
|
||||
|
63
spec/json_types.d
Normal file
63
spec/json_types.d
Normal file
@ -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
|
||||
{
|
||||
}
|
@ -19,8 +19,8 @@ describe Propane do
|
||||
end
|
||||
end
|
||||
|
||||
def compile(test_file)
|
||||
result = system(*%w[gdc -funittest -o spec/run/testparser spec/run/testparser.d], test_file)
|
||||
def compile(*test_files)
|
||||
result = system(*%w[gdc -funittest -o spec/run/testparser spec/run/testparser.d -Ispec], *test_files)
|
||||
expect(result).to be_truthy
|
||||
end
|
||||
|
||||
@ -334,4 +334,190 @@ EOF
|
||||
expect(results.stderr).to eq ""
|
||||
expect(results.status).to eq 0
|
||||
end
|
||||
|
||||
it "allows creating a JSON parser" do
|
||||
write_grammar <<EOF
|
||||
<<
|
||||
import std.math;
|
||||
import json_types;
|
||||
string string_value;
|
||||
>>
|
||||
|
||||
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]+)?/ <<
|
||||
double n;
|
||||
bool negative;
|
||||
size_t i = 0u;
|
||||
if (match[i] == '-')
|
||||
{
|
||||
negative = true;
|
||||
i++;
|
||||
}
|
||||
while ('0' <= match[i] && match[i] <= '9')
|
||||
{
|
||||
n *= 10.0;
|
||||
n += (match[i] - '0');
|
||||
i++;
|
||||
}
|
||||
if (match[i] == '.')
|
||||
{
|
||||
i++;
|
||||
double mult = 0.1;
|
||||
while ('0' <= match[i] && match[i] <= '9')
|
||||
{
|
||||
n += mult * (match[i] - '0');
|
||||
mult /= 10.0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (match[i] == 'e' || match[i] == 'E')
|
||||
{
|
||||
bool exp_negative;
|
||||
i++;
|
||||
if (match[i] == '-')
|
||||
{
|
||||
exp_negative = true;
|
||||
i++;
|
||||
}
|
||||
else if (match[i] == '+')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
long exp;
|
||||
while ('0' <= match[i] && match[i] <= '9')
|
||||
{
|
||||
exp *= 10;
|
||||
exp += (match[i] - '0');
|
||||
i++;
|
||||
}
|
||||
if (exp_negative)
|
||||
{
|
||||
exp = -exp;
|
||||
}
|
||||
n = pow(n, exp);
|
||||
}
|
||||
if (negative)
|
||||
{
|
||||
n = -n;
|
||||
}
|
||||
$$ = 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
|
||||
|
55
spec/test_parsing_json.d
Normal file
55
spec/test_parsing_json.d
Normal file
@ -0,0 +1,55 @@
|
||||
import testparser;
|
||||
import std.stdio;
|
||||
import json_types;
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
string input = ``;
|
||||
auto parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
|
||||
input = `{}`;
|
||||
parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
assert(cast(JSONObject)parser.result);
|
||||
|
||||
input = `[]`;
|
||||
parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
assert(cast(JSONArray)parser.result);
|
||||
|
||||
input = `-45.6`;
|
||||
parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
assert(cast(JSONNumber)parser.result);
|
||||
assert((cast(JSONNumber)parser.result).value == -45.6);
|
||||
|
||||
input = `2E-2`;
|
||||
parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
assert(cast(JSONNumber)parser.result);
|
||||
assert((cast(JSONNumber)parser.result).value == 0.02);
|
||||
|
||||
input = `{"hi":true}`;
|
||||
parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
assert(cast(JSONObject)parser.result);
|
||||
JSONObject o = cast(JSONObject)parser.result;
|
||||
assert(o.value["hi"]);
|
||||
assert(cast(JSONTrue)o.value["hi"]);
|
||||
|
||||
input = `{"ff": false, "nn": null}`;
|
||||
parser = new Testparser.Parser(input);
|
||||
assert(parser.parse());
|
||||
assert(cast(JSONObject)parser.result);
|
||||
o = cast(JSONObject)parser.result;
|
||||
assert(o.value["ff"]);
|
||||
assert(cast(JSONFalse)o.value["ff"]);
|
||||
assert(o.value["nn"]);
|
||||
assert(cast(JSONNull)o.value["nn"]);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user