jStreamReader[stream:_String|_File|_InputStream]:=Module[{jStreamReader,jStreamData},jStreamReader~ClearAttributes~Temporary;jStreamData~ClearAttributes~Temporary;jStreamData=<|"InString"False,"BlockDepth"<|Association0,List0,CompoundExpression0|>,"BlockStack"{},"Cache"Internal`Bag[],"CacheStack"{},"CachePush"Function[Internal`StuffBag[jStreamData["Cache"],#]],"CacheRecurse"Function[jStreamData["CacheStack"]={jStreamData["CacheStack"],jStreamData["Cache"]};jStreamData["Cache"]=Internal`Bag[];],"CacheReset"Function[With[{c=jStreamData["CacheStack"]},jStreamData["CacheStack"]=c[[1]];jStreamData["Cache"]=c[[2]];]],"CachePart"Function[Internal`BagPart[jStreamData["Cache"],#]],"CacheClear"Function[jStreamData["Cache"]=Internal`Bag[];],"CacheDump"Function[With[{data=Internal`BagPart[jStreamData["Cache"],All]},jStreamData["Cache"]=Internal`Bag[];data]],"Stream"Replace[stream,{_File|_String?FileExistsQOpenRead[stream],_StringStringToStream[stream]}]|>;jStreamReader["HeldSymbol"]=Hold[jStreamData];jStreamReader["Symbol"]:=Unevaluated[jStreamData];jStreamReader["Data"]:=jStreamData;jStreamReader["Next"]:=jStreamReadToken[jStreamReader];jStreamReader[s__]:=jStreamData[s];jStreamReader/:Set[jStreamReader[p___],v_]:=jStreamData[p]=v;jStreamReader/:ReadString[jStreamReader,a___]:=ReadString[jStreamData["Stream"],a];jStreamReader/:Read[jStreamReader,a___]:=Read[jStreamData["Stream"],a];jStreamReader/:ReadList[jStreamReader,a___]:=ReadList[jStreamData["Stream"],a];jStreamReader/:StreamPosition[jStreamReader]:=StreamPosition@jStreamData["Stream"];jStreamReader/:SetStreamPosition[jStreamReader,p_]:=SetStreamPosition[jStreamData["Stream"],p];jStreamReader/:Close[jStreamReader]:=(Close@jStreamData["Stream"];jStreamData//Remove);jStreamReader]$jStreamBracketTokenIndicators={"{","}","[","]","(",")"};$jStreamChunkTokenIndicators={",",":"};$jStreamStringTokenIndicators={"\""};$jStreamInStringTokenIndicators={"\\\"","\""};$jStreamPossibleTokenIndicators=Alternatives@@Join[$jStreamStringTokenIndicators,$jStreamBracketTokenIndicators,$jStreamChunkTokenIndicators];$jStreamInStringTokenIndicators=Alternatives@@$jStreamInStringTokenIndicators;$jStreamBracketTokenIndicators=Alternatives@@$jStreamBracketTokenIndicators;$jStreamBracketMap=<|"{"{Opening,Association},"}"{Closing,Association},"["{Opening,List},"]"{Closing,List},"("{Opening,CompoundExpression},")"{Closing,CompoundExpression}|>;jStreamReadToSep[reader_]:=Module[{sp=StreamPosition@reader,strm=reader["Stream"],ret,sep},ret=With[{test=Read[strm,Character]},If[test===EndOfFile,Throw[EndOfFile]];SetStreamPosition[strm,sp];If[reader["InString"],If[StringMatchQ[test,$jStreamInStringTokenIndicators]||StringMatchQ[test<>"\"",$jStreamInStringTokenIndicators],"",ReadString[strm,$jStreamInStringTokenIndicators]],If[StringMatchQ[test,$jStreamPossibleTokenIndicators],"",ReadString[strm,$jStreamPossibleTokenIndicators]]]];sep=If[reader["InString"],With[{ec=Read[reader,Character]},If[ec==="\\",ec<>Read[reader,Character],ec]],Read[reader,Character]];If[StringMatchQ[sep,$jStreamBracketTokenIndicators]&&StringLength@StringTrim[ret]>0,SetStreamPosition[reader,StreamPosition[reader]-1];sep=""];{ret,sep,sp}];jStreamHandleSepData[reader_,{ret_,sep_,sp_}]:=With[{sepData=$jStreamBracketMap[sep]},Which[sep==="",{ret,sep,Value,Expression},sep===":",{ret,sep,Key,None},sep===",",{ret,sep,Value,Expression},sep==="\""&&reader["InString"],reader["InString"]=False;{ret,sep,None,String},sep==="\"",reader["InString"]=True;{ret,sep,None,Continue},sep==="\\\"",{ret,sep,None,Continue},sepData[[1]]===Closing,If[reader["BlockStack"][[-1]]sepData[[2]],reader["BlockDepth",sepData[[2]]]=Max@{reader["BlockDepth",sepData[[2]]]-1,0};reader["BlockStack"]=Drop[reader["BlockStack"],-1]];{ret,sep,sepData,Expression},sepData[[1]]===Opening,reader["BlockDepth",sepData[[2]]]=Max@{reader["BlockDepth",sepData[[2]]]-1,0};reader["BlockStack"]=Append[reader["BlockStack"],sepData[[2]]];{ret,sep,sepData,None},True,{ret,sep,sepData,Expression}]];jStreamReadTokenSegments[reader_]:=Block[{segs},segs={None,jStreamHandleSepData[reader,jStreamReadToSep[reader]]};While[segs[[-1,-1]]===Continue,segs={segs,jStreamHandleSepData[reader,jStreamReadToSep[reader]]}];Cases[segs,{_String,_String,__},∞]]jStreamBuildToken[segs_]:={Switch[segs[[-1,-1]],None,Null,String,{ToExpression@StringJoin@segs[[All,;;2]],String},_,{Replace[StringTrim@StringJoin@segs[[-1,1]],{"null"Null,e_:>ToExpression@e}],segs[[-1,-1]]}],Replace[segs[[-1,-2]],{{o_,"{}"}{o,Association},{o_,"[]"}{o,List},{o_,"()"}:>CompoundExpression}]}jStreamReadToken[reader_]:=Catch@jStreamBuildToken@jStreamReadTokenSegments[reader];