On Thursday, September 12, 2019 at 9:11:03 PM UTC-5, luser droog wrote:
On Sunday, September 8, 2019 at 4:33:23 PM UTC-5, [email protected]d wrote:
JSON.utf8 is now implemented (although it doesn't currently convert surrogate pairs into a single UTF-8 codepoint), and another change as suggested by some of the other follow-up messages to my first message
have also been implemented. Also, the "dot stuffing" of this message is (hopefully) correct now; it was a bug in the NNTP software I was using,
but I have now corrected that bug (hopefully).
Also, I would like to know if you have any use for this, and especially if you have found any bugs in it. (This is not mandatory though; it is public domain, so you are allowed to do whatever you want with it.)
I'm not sure how useful it is. Whenever I've needed to send data to postscript,
it has always been fairly easy to output valid postscript code. But I think this *is* a fun little exercise. I spent this afternoon/evening writing my own using the parser combinators. Probably some bugs in edge cases I haven't considered. But simple tests appear to be working! It doesn't do any utf conversion. It doesn't remove whitespace characters.
I'd be curious to see a speed comparison between our two programs (if only
to see how much slower mine probably is). But I'm not quite curious enough
to do it myself.
<snip>
Improved my code to handle spaces and nested structures. I had to
debug and modify part of the parser combinator library to get it
to work.
The problem I was having was the result from a parser
produced by the 'maybe' combinator. A maybe parser has to succeed
regardless of the success or failure of its child parser. So in the
case where the child parser fails, 'maybe' has to return *something*.
Earlier I had it set up to return an empty array [], but the problem
now was that some other part of the machinery (haven't tracked it
down precisely yet) was interpreting that as failure instead of
success with an empty result.
I changed it now to return the name /0. Since I'm not using names
anywhere in the data (relying on the automatic behavior of 'def')
I can detect these as part of the scaffolding of the parse tree.
I can't use 'null' because json data may contain the keyword null.
This version doesn't actually convert null (or true or false) but
it's a trivial change.
The next issue is: I don't understand what to do with unicode
characters if they are discovered. It appears that OP's code
reads in the multibyte sequences, constructs the codepoint in
an int, and then truncates that to 8 bits and stores it in a
string. That doesn't seem right, but I can't really think of
anything better. Maybe an option either to leave the utf8 alone,
or convert to arrays of integers? It's not clear to me what
a PostScript program could hope to do with unicode data.
So I haven't written any utf8 handling. If I do add it, I think
it should be added to the parser library itself as an input
filter. The C version has these already.
Additional referenced files at latest commit:
https://github.com/luser-dr00g/pcomb/tree/d4cc78d862c84873fb05a593df2ea5d878988b81/ps
%!
%cf.
https://tools.ietf.org/html/rfc7159
(pc9re2.ps)run
%errordict/typecheck{/typecheck = pstack / = countexecstack array execstack == quit}put
%errordict/rangecheck{/rangecheck = pstack / = countexecstack array execstack == quit}put
/SEQ {{seq}reduce} def
/PLUS {{plus}reduce} def
/str {{lit}map SEQ} def
/filter-zeros { { dup /0 eq {pop} if } map } def
/snip-ends { 1 1 index length 2 sub getinterval } def
/! { { dup /0 eq { pop [] } if } using } def
/maybe! { maybe ! } def
/many! { many ! } def
/dump { dup first exch
second dup type /nametype eq 1 index /0 eq and { pop }{ dump } ifelse } def
/to-array { dup type /arraytype ne { one }{ [ exch dump ] } ifelse } def /to-pairs {
dup length 1 eq { first pairs }{
[ exch dup first exch second dump ]
{spill spill} map pairs
} ifelse
} def
/ws ( \t\n\r) anyof many def
/begin-array //ws ([) char xthen //ws thenx def
/begin-object //ws ({) char xthen //ws thenx def
/end-array //ws (]) char xthen //ws thenx def
/end-object //ws (}) char xthen //ws thenx def
/name-separator //ws (:) char xthen //ws thenx def
/value-separator //ws (,) char xthen //ws thenx def
/value {-777 exec} def
/decimal-point (.) char def
/digit1-9 (19) spill range def
/digit (09) spill range def
/Jzero (0) char def
/e (eE) anyof def
/Jplus (+) char def
/minus (-) char def
/frac //decimal-point //digit some seq def
/expn [ //e //minus //Jplus plus maybe! //digit some ] SEQ def
/int //Jzero //digit1-9 //digit many seq plus def
/number [ //minus maybe! //int //frac maybe! //expn maybe! ] SEQ
{
flatten filter-zeros to-string
dup (.) search { pop pop pop cvr }{
pop dup (e) search { pop pop pop cvr }{
pop dup (E) search { pop pop pop cvr }{ pop cvi } ifelse
} ifelse
} ifelse
} using
def
/quotation-mark (") char def
/unescaped [ 16#20 16#21 range 16#23 16#5B range 16#5D 16#10FFFF range ] PLUS def
/escape (\\) char def
/4hexdig (u) char //digit (AF) spill range plus 3{dup seq}repeat seq def
/escape-sequence //escape [ ("\\/bfnrt) anyof //4hexdig ] PLUS seq def
/Jchar //unescaped //escape-sequence plus def
/Jstring [ //quotation-mark //Jchar many! //quotation-mark ] SEQ
{ flatten filter-zeros snip-ends to-string } using
def
/member //Jstring //name-separator thenx //value seq
{ one } using
def
/Jobject //begin-object
//member xthen
//value-separator //member xthen many! seq maybe!
//end-object thenx
{ to-pairs } using
def
/Jarray //begin-array
//value xthen
//value-separator //value xthen many! seq maybe!
//end-array thenx
{ to-array } using
def
//value 0 [ (false) str (null) str (true) str
//Jobject //Jarray //number //Jstring ] PLUS put
/JSON-text //ws //value xthen //ws thenx def
/JSON-parse {
JSON-text first first
} def
%(4) dup string-input JSON-parse pc
%( 4) dup string-input JSON-parse pc
%(4 ) dup string-input JSON-parse pc
%( 4 ) dup string-input JSON-parse pc
%( 4.0 ) dup string-input JSON-parse pc
( 4e3 ) dup string-input JSON-parse pc
( "4" ) dup string-input JSON-parse pc
( [ 4 ] ) dup string-input JSON-parse pc
( [ 4, 5 ] ) dup string-input JSON-parse pc
( [ 3, [ 4, [ 5 ] ] ] ) dup string-input JSON-parse pc
( {"a":4,"b":5} ) dup string-input JSON-parse ps === clear
( { "a" : 4 , "b" : 5 } ) dup string-input JSON-parse ps === clear
( [ {"a":4,"b":5}, 6, {"c":"7"}] ) dup string-input JSON-parse ps === clear quit
Output:
$ make
gsnd -dNOSAFER pc9json.ps
GPL Ghostscript 9.27 (2019-04-04)
Copyright (C) 2018 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
stack:
4000.0
( 4e3 )
stack:
(4)
( "4" )
stack:
[4]
( [ 4 ] )
stack:
[4 5]
( [ 4, 5 ] )
stack:
[3 [4 [5]]]
( [ 3, [ 4, [ 5 ] ] ] )
stack:
-dict-
( {"a":4,"b":5} )
<< /a 4 /b 5 >>
stack:
-dict-
( { "a" : 4 , "b" : 5 } )
<< /a 4 /b 5 >>
stack:
[-dict- 6 -dict-]
( [ {"a":4,"b":5}, 6, {"c":"7"}] )
[<< /a 4 /b 5 >> 6 << /c (7) >>]
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)