Changed formatting to match Markus Triska's as much as I can tell

This commit is contained in:
panasenco
2021-04-18 23:44:10 -07:00
parent 0e73b53803
commit 20f192daa1

View File

@@ -47,7 +47,7 @@
:- use_module(library(lists)). :- use_module(library(lists)).
:- use_module(library(reif)). :- use_module(library(reif)).
/* The DCGs are written to match the McKeeman Form presented on the right side of https://www.json.org/json-en.html /* The DCGs are written to match the McKeeman form presented on the right side of https://www.json.org/json-en.html
almost perfectly. Note that the McKeeman form conflicts some with the pictures on the left side. */ almost perfectly. Note that the McKeeman form conflicts some with the pictures on the left side. */
json_chars(Internal) --> json_element(Internal). json_chars(Internal) --> json_element(Internal).
@@ -55,13 +55,13 @@ json_chars(Internal) --> json_element(Internal).
different types of values based on their principal functor. The principal functors match the types defined in different types of values based on their principal functor. The principal functors match the types defined in
the JSON Schema spec here: https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.1.1 the JSON Schema spec here: https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.1.1
Down the line we'll incorporate more JSON Schema support, but this is it for now. */ Down the line we'll incorporate more JSON Schema support, but this is it for now. */
json_value(object(Assoc)) --> json_object(Assoc). json_value(object(Assoc)) --> json_object(Assoc).
json_value(array(List)) --> json_array(List). json_value(array(List)) --> json_array(List).
json_value(string(Chars)) --> json_string(Chars). json_value(string(Chars)) --> json_string(Chars).
json_value(number(Number)) --> json_number(Number). json_value(number(Number)) --> json_number(Number).
json_value(boolean(true)) --> "true". json_value(boolean(true)) --> "true".
json_value(boolean(false)) --> "false". json_value(boolean(false)) --> "false".
json_value(null) --> "null". json_value(null) --> "null".
/* Read Bob Kowalski's "Algorithm = Logic + Control": /* Read Bob Kowalski's "Algorithm = Logic + Control":
https://www.doc.ic.ac.uk/~rak/papers/algorithm%20=%20logic%20+%20control.pdf https://www.doc.ic.ac.uk/~rak/papers/algorithm%20=%20logic%20+%20control.pdf
@@ -73,38 +73,36 @@ json_value(null) --> "null".
Maybe at some point in the future we'll have a library that takes a pure logic character parsing/generating DCG Maybe at some point in the future we'll have a library that takes a pure logic character parsing/generating DCG
and 'injects' control strategy into it. We aren't there yet... */ and 'injects' control strategy into it. We aren't there yet... */
json_object(EmptyAssoc) --> {empty_assoc(EmptyAssoc)}, "{", json_ws, "}". json_object(EmptyAssoc) --> {empty_assoc(EmptyAssoc)}, "{", json_ws, "}".
json_object(Assoc) --> json_object(Assoc) -->
{ { ( nonvar(Assoc) ->
nonvar(Assoc) -> \+ empty_assoc(Assoc),
\+ empty_assoc(Assoc), assoc_to_list(Assoc, [Pair|Pairs])
assoc_to_list(Assoc, [Pair|Pairs]) ; true
; true ) },
}, "{",
"{", json_members([Pair|Pairs]),
json_members([Pair|Pairs]), "}",
"}", { ( var(Assoc) ->
{ list_to_assoc([Pair|Pairs], Assoc)
var(Assoc) -> ; true
list_to_assoc([Pair|Pairs], Assoc) ) }.
; true
}.
json_members([Key-Value]) --> json_member(Key, Value). json_members([Key-Value]) --> json_member(Key, Value).
json_members([Key-Value | Pairs]) --> json_member(Key, Value), ",", json_members(Pairs). json_members([Key-Value | Pairs]) --> json_member(Key, Value), ",", json_members(Pairs).
json_member(Key, Value) --> json_ws, json_string(Key), json_ws, ":", json_element(Value). json_member(Key, Value) --> json_ws, json_string(Key), json_ws, ":", json_element(Value).
json_array([]) --> "[", json_ws, "]". json_array([]) --> "[", json_ws, "]".
json_array([Value|Values]) --> "[", json_elements([Value|Values]), "]". json_array([Value|Values]) --> "[", json_elements([Value|Values]), "]".
json_elements([Value]) --> json_element(Value). json_elements([Value]) --> json_element(Value).
json_elements([Value|Values]) --> json_element(Value), ",", json_elements(Values). json_elements([Value|Values]) --> json_element(Value), ",", json_elements(Values).
json_element(Value) --> json_ws, json_value(Value), json_ws. json_element(Value) --> json_ws, json_value(Value), json_ws.
json_string(Chars) --> "\"", json_characters(Chars), "\"". json_string(Chars) --> "\"", json_characters(Chars), "\"".
json_characters("") --> "". json_characters("") --> "".
json_characters([Char|Chars]) --> json_character(Char), json_characters(Chars). json_characters([Char|Chars]) --> json_character(Char), json_characters(Chars).
/* A directly printable character is defined by the JSON spec as a character between 0020 and 10FFFF except the /* A directly printable character is defined by the JSON spec as a character between 0020 and 10FFFF except the
@@ -114,114 +112,100 @@ json_characters([Char|Chars]) --> json_character(Char), json_characters(Chars).
If we moved the block containing `char_code/2` up before `[PrintChar]`, we would still be able to generate JSON, If we moved the block containing `char_code/2` up before `[PrintChar]`, we would still be able to generate JSON,
but attempting to parse JSON would cause an instantiation error. */ but attempting to parse JSON would cause an instantiation error. */
escape_map([ escape_map([
'"' - '"', '"' - '"',
('\\') - ('\\'), ('\\') - ('\\'),
('/') - ('/'), ('/') - ('/'),
'\b' - 'b', '\b' - 'b',
'\f' - 'f', '\f' - 'f',
'\n' - 'n', '\n' - 'n',
'\r' - 'r', '\r' - 'r',
'\t' - 't' '\t' - 't' ]).
]).
json_character(PrintChar) --> json_character(PrintChar) -->
[PrintChar], [PrintChar],
{ { escape_map(EscapeMap),
escape_map(EscapeMap), \+ member(PrintChar-_, EscapeMap),
\+ member(PrintChar-_, EscapeMap), char_code(PrintChar, PrintCharCode),
char_code(PrintChar, PrintCharCode), PrintCharCode in 32..1114111 /* 20.10FFFF */ }.
PrintCharCode in 32..1114111 /* 20.10FFFF */
}.
json_character(EscapeChar) --> "\\", json_escape(EscapeChar). json_character(EscapeChar) --> "\\", json_escape(EscapeChar).
json_escape(EscapeChar) --> json_escape(EscapeChar) -->
[PrintChar], [PrintChar],
{ { escape_map(EscapeMap),
escape_map(EscapeMap), member(EscapeChar-PrintChar, EscapeMap) }.
member(EscapeChar-PrintChar, EscapeMap)
}.
json_escape(EscapeChar) --> json_escape(EscapeChar) -->
"u", "u",
{ /* Logic: Define the domain of the escape character as well as the relationship between the escape character /* Logic: Define the domain of the escape character as well as the relationship between the escape character
and the four hexes */ and the four hexes */
[H1, H2, H3, H4] ins 0..15, { [H1, H2, H3, H4] ins 0..15,
EscapeCharCode in 0..65535, EscapeCharCode in 0..65535,
EscapeCharCode #= H1 * 16^3 + H2 * 16^2 + H3 * 16 + H4 EscapeCharCode #= H1 * 16^3 + H2 * 16^2 + H3 * 16 + H4,
}, /* Control: Get the code of the escape character if we can. Otherwise we'll end up backtracking over 65,536
{ /* Control: Get the code of the escape character if we can. Otherwise we'll end up backtracking over 65,536 possible hex values.
possible hex values. Logic: Only the first 32 Unicode characters not escaped in the escape map are eligible for \u-escaping
Logic: Only the first 32 Unicode characters not escaped in the escape map are eligible for \u-escaping when generating. However, we want to be able to parse any of the 65,536 \u-escaped values when parsing. */
when generating. However, we want to be able to parse any of the 65,536 \u-escaped values when parsing. */ ( nonvar(EscapeChar) ->
nonvar(EscapeChar) -> char_code(EscapeChar, EscapeCharCode),
char_code(EscapeChar, EscapeCharCode), EscapeCharCode in 0..31,
EscapeCharCode in 0..31, escape_map(EscapeMap),
escape_map(EscapeMap), \+ member(EscapeChar-_, EscapeMap)
\+ member(EscapeChar-_, EscapeMap) ; true
; true )
}, },
json_hex(H1), json_hex(H1),
json_hex(H2), json_hex(H2),
json_hex(H3), json_hex(H3),
json_hex(H4), json_hex(H4),
{ /* Control + Logic: Get the escape character atom from the character code computed from the hexes. */ /* Control + Logic: Get the escape character atom from the character code computed from the hexes. */
var(EscapeChar) -> { ( var(EscapeChar) ->
char_code(EscapeChar, EscapeCharCode) char_code(EscapeChar, EscapeCharCode)
; true ; true
}. ) }.
json_hex(Digit) --> json_digit(Digit). json_hex(Digit) --> json_digit(Digit).
json_hex(10) --> "a". json_hex(10) --> "a".
json_hex(11) --> "b". json_hex(11) --> "b".
json_hex(12) --> "c". json_hex(12) --> "c".
json_hex(13) --> "d". json_hex(13) --> "d".
json_hex(14) --> "e". json_hex(14) --> "e".
json_hex(15) --> "f". json_hex(15) --> "f".
json_hex(10) --> "A". json_hex(10) --> "A".
json_hex(11) --> "B". json_hex(11) --> "B".
json_hex(12) --> "C". json_hex(12) --> "C".
json_hex(13) --> "D". json_hex(13) --> "D".
json_hex(14) --> "E". json_hex(14) --> "E".
json_hex(15) --> "F". json_hex(15) --> "F".
/* Here we are going to write completely different DCGs for parsing and generating, and rely on built-in /* Here we are going to write completely different DCGs for parsing and generating, and rely on built-in
predicates. However, the underlying logic remains the same. */ predicates. However, the underlying logic remains the same. */
json_number(Number) --> json_number(Number) -->
{ { ( nonvar(Number) ->
nonvar(Number) -> number_chars(Number, NumberChars)
number_chars(Number, NumberChars) ; false
; false ) },
},
NumberChars. NumberChars.
json_number(Number) --> json_number(Number) -->
{ { var(Number) },
var(Number)
},
json_sign_noplus(Sign), json_sign_noplus(Sign),
json_integer(Integer), json_integer(Integer),
json_fraction(Fraction), json_fraction(Fraction),
json_exponent(Exponent), json_exponent(Exponent),
{ { Number is Sign * (Integer + Fraction) * 10.0 ^ Exponent }.
Number is Sign * (Integer + Fraction) * 10.0 ^ Exponent
}.
json_integer(Digit) --> json_digit(Digit). json_integer(Digit) --> json_digit(Digit).
json_integer(TotalValue) --> json_integer(TotalValue) -->
json_onenine(FirstDigit), json_onenine(FirstDigit),
json_digits(RemainingValue, Power), json_digits(RemainingValue, Power),
{ { TotalValue #= FirstDigit * 10 ^ (Power + 1) + RemainingValue }.
TotalValue #= FirstDigit * 10 ^ (Power + 1) + RemainingValue
}.
json_digits(Digit, 0) --> json_digit(Digit). json_digits(Digit, 0) --> json_digit(Digit).
json_digits(Value, Power) --> json_digits(Value, Power) -->
json_digit(FirstDigit), json_digit(FirstDigit),
json_digits(RemainingValue, NextPower), json_digits(RemainingValue, NextPower),
{ { Power #= NextPower + 1,
Power #= NextPower + 1, Value #= FirstDigit * 10^Power + RemainingValue }.
Value #= FirstDigit * 10^Power + RemainingValue
}.
json_digit(0) --> "0". json_digit(0) --> "0".
json_digit(Digit) --> json_onenine(Digit). json_digit(Digit) --> json_onenine(Digit).
json_onenine(1) --> "1". json_onenine(1) --> "1".
@@ -234,31 +218,27 @@ json_onenine(7) --> "7".
json_onenine(8) --> "8". json_onenine(8) --> "8".
json_onenine(9) --> "9". json_onenine(9) --> "9".
json_fraction(0) --> "". json_fraction(0) --> "".
json_fraction(Fraction) --> json_fraction(Fraction) -->
".", ".",
json_digits(Value, Power), json_digits(Value, Power),
{ { Fraction is Value / 10 ^ (Power + 1) }.
Fraction is Value / 10 ^ (Power + 1)
}.
json_exponent(0) --> "". json_exponent(0) --> "".
json_exponent(Exponent) --> json_exponent(Exponent) -->
json_exponent_signifier, json_exponent_signifier,
json_sign(Sign), json_sign(Sign),
json_digits(Value, _), json_digits(Value, _),
{ { Exponent #= Sign * Value }.
Exponent #= Sign * Value
}.
json_exponent_signifier --> "E". json_exponent_signifier --> "E".
json_exponent_signifier --> "e". json_exponent_signifier --> "e".
json_sign_noplus(1) --> "". json_sign_noplus(1) --> "".
json_sign_noplus(-1) --> "-". json_sign_noplus(-1) --> "-".
json_sign(Sign) --> json_sign_noplus(Sign). json_sign(Sign) --> json_sign_noplus(Sign).
json_sign(1) --> "+". json_sign(1) --> "+".
json_ws --> "". json_ws --> "".
json_ws --> " ", json_ws. json_ws --> " ", json_ws.