import "../test/setup" ; import { Parjser } from "../lib/internal/parjser" ; import { ResultKind } from "../lib/internal/result" ; import { later , many , manySepBy , map , or , stringify , qthen , thenq , then , between } from "../lib/combinators" ; import { anyStringOf , float , string , stringLen , anyCharOf , noCharOf , whitespace } from "../lib/index" ; import { visualizeTrace } from "../lib/internal/trace-visualizer" ; class JsonNumber { constructor ( public value ) { } } class JsonString { constructor ( public value ) { } } class JsonBool { constructor ( public value ) { } } class JsonArray { constructor ( public value ) { } } class JsonObjectProperty { constructor ( public name , public value ) { } } class JsonObject { constructor ( public value ) { } } type JsonValue = JsonNumber | JsonString | JsonBool | JsonArray | JsonObject ; let escapes = { "\"" : `"` , "\\" : "\\" , "/" : "/" , f : "\f" , n : "\n" , r : "\r" , t : "\t" } ; let pJsonValue = later < JsonValue > ( ) ; let pEscapeChar = anyCharOf ( Object . getOwnPropertyNames ( escapes ) . join ( ) ) . pipe ( map ( char => escapes [ char ] as string ) ) ; let pEscapeUnicode = string ( "u" ) . pipe ( qthen ( stringLen ( 4 ) . pipe ( map ( str => parseInt ( str , 16 ) ) , map ( x => String . fromCharCode ( x ) ) ) ) ) ; let pEscapeAny = string ( "\\" ) . pipe ( qthen ( pEscapeChar . pipe ( or ( pEscapeUnicode ) ) ) ) ; let pCharOrEscape = pEscapeAny . pipe ( or ( noCharOf ( '"' ) ) ) ; let pStr = pCharOrEscape . pipe ( many ( ) , stringify ( ) , between ( '"' ) ) ; let pJsonString = pStr . pipe ( map ( str => new JsonString ( str ) ) ) ; let pNumber = float ( ) . pipe ( map ( n => new JsonNumber ( n ) ) ) ; let pBool = anyStringOf ( "true" , "false" ) . pipe ( map ( str => new JsonBool ( str === "true" ) ) ) ; let pArray = pJsonValue . pipe ( manySepBy ( "," ) , between ( "[" , "]" ) , map ( arr => new JsonArray ( arr ) ) ) ; let pObjectProperty = pStr . pipe ( thenq ( string ( ":" ) . pipe ( between ( whitespace ( ) ) ) ) , then ( pJsonValue ) , between ( whitespace ( ) ) , map ( ( [ name , value ] ) => { return new JsonObjectProperty ( name , value ) ; } ) ) ; let pObject = pObjectProperty . pipe ( manySepBy ( "," ) , between ( "{" , "}" ) , map ( properties => new JsonObject ( properties ) ) ) ; pJsonValue . init ( pJsonString . pipe ( or ( pNumber , pBool , pArray , pObject ) , between ( whitespace ( ) ) ) ) ; function astToObject ( obj ) { if ( obj instanceof JsonNumber ) { return obj . value ; } else if ( obj instanceof JsonString ) { return obj . value ; } else if ( obj instanceof JsonBool ) { return obj . value ; } else if ( obj instanceof JsonArray ) { return obj . value . map ( x => astToObject ( x ) ) ; } else if ( obj instanceof JsonObject ) { let res = { } ; for ( let prop of obj . value ) { res [ prop . name ] = astToObject ( prop . value ) ; } return res ; } } let result = pJsonValue . parse ( `{"a" : 2, 


"b\\"" : 
44325, "z" : "hi!", "a" : true,
 "array" : ["hi", 1, {"a" :    "b\\"" }, [], {}]}` ) ; if ( result . kind !== ResultKind . Ok ) { console . log ( visualizeTrace ( result . trace ) ) ; } else { console . log ( astToObject ( result . value ) ) ; }