GitHub

@@ -0,0 +1,176 @@

1+

! Copyright (C) 2025 John Benediktsson

2+

! See https://factorcode.org/license.txt for BSD license

3+4+

USING: arrays combinators hash-sets hashtables kernel make math

5+

math.parser peg peg.parsers sequences splitting strings

6+

strings.parser unicode vectors ;

7+8+

IN: edn

9+10+

TUPLE: keyword name ;

11+12+

TUPLE: symbol name ;

13+14+

TUPLE: tagged name value ;

15+16+

<PRIVATE

17+18+

: spaces ( -- parser )

19+

[ blank? ] satisfy repeat1 ;

20+21+

: newline ( -- parser )

22+

"\n" token "\r\n" token 2choice ;

23+24+

: comments ( -- parser )

25+

";" token [ CHAR: \n = not ] satisfy repeat0 newline optional 3seq ;

26+27+

: spaces-or-comments ( -- parser )

28+

spaces comments 2choice repeat1 ;

29+30+

: nil-parser ( -- parser )

31+

"nil" token [ drop null ] action ;

32+33+

: boolean-parser ( -- parser )

34+

"true" token [ drop t ] action

35+

"false" token [ drop f ] action

36+

2choice ;

37+38+

: escaped ( -- parser )

39+

"\\" token hide [ "\"\\befnrt" member-eq? ] satisfy 2seq

40+

[ first escape ] action ;

41+42+

: string-parser ( -- parser )

43+

escaped [ CHAR: \" = not ] satisfy 2choice repeat0

44+

"\"" dup surrounded-by [ >string ] action ;

45+46+

: char-parser ( -- parser )

47+

"\\" token hide [ blank? not ] satisfy repeat1 [

48+

>string {

49+

{ "newline" [ CHAR: \n ] }

50+

{ "return" [ CHAR: \r ] }

51+

{ "space" [ CHAR: \s ] }

52+

{ "tab" [ CHAR: \t ] }

53+

[ "u" ?head [ hex> ] [ first ] if ]

54+

} case

55+

] action 2seq [ first ] action ;

56+57+

: keyword-parser ( -- parser )

58+

":" token hide

59+

[ blank? not ] satisfy repeat1 [ >string ] action

60+

2seq [ first keyword boa ] action ;

61+62+

: symbol-parser ( -- parser )

63+

[ [ digit? not ] [ [ alpha? ] [ ".*+!-_?$%&=<>" member? ] bi or ] bi and ] satisfy

64+

[ [ alpha? ] [ ".*+!-_?$%&=<>" member? ] bi or ] satisfy repeat0 2seq

65+

[ first2 swap prefix >string ] action

66+

"/" token list-of [ "/" join symbol boa ] action ;

67+68+

: sign ( -- parser )

69+

"+" token "-" token 2choice ;

70+71+

: decdigit ( -- parser )

72+

CHAR: 0 CHAR: 9 range ;

73+74+

: int-parser ( -- parser )

75+

sign optional decdigit repeat1 "N" token hide optional 3seq

76+

[ "" concat-as string>number ] action ;

77+78+

: exponent ( -- parser )

79+

"e" token "E" token 2choice sign optional

80+

decdigit repeat1 3seq [ "" concat-as ] action ;

81+82+

: float-parser ( -- parser )

83+

[ sign optional , decdigit repeat1 , exponent , ] seq*

84+

[ sign optional , decdigit repeat1 , "." token , decdigit repeat1 , exponent optional , ] seq*

85+

2choice [ "" concat-as string>number ] action ;

86+87+

DEFER: value-parser

88+89+

: discard-parser ( -- parser )

90+

"#_" token spaces-or-comments optional value-parser 3seq ;

91+92+

: ?value-parser ( -- parser )

93+

discard-parser hide comments hide value-parser 3choice ;

94+95+

: values-parser ( -- parser )

96+

[

97+

spaces-or-comments optional hide ,

98+

?value-parser ,

99+

spaces-or-comments hide ?value-parser 2seq repeat0

100+

[ concat ] action ,

101+

spaces-or-comments optional hide ,

102+

] seq* [ dup length 1 > [ first2 swap prefix ] [ ?first ] if ] action ;

103+104+

: list-parser ( -- parser )

105+

[

106+

"(" token hide , spaces-or-comments optional hide ,

107+

values-parser optional ,

108+

spaces-or-comments optional hide , ")" token hide ,

109+

] seq* [ ?first >array ] action ;

110+111+

: vector-parser ( -- parser )

112+

[

113+

"[" token hide , spaces-or-comments optional hide ,

114+

values-parser optional ,

115+

spaces-or-comments optional hide , "]" token hide ,

116+

] seq* [ ?first >vector ] action ;

117+118+

: pair-parser ( -- parser )

119+

value-parser spaces-or-comments hide value-parser 3seq ;

120+121+

: pairs-parser ( -- parser )

122+

pair-parser

123+

[ [ CHAR: , = ] [ blank? ] bi or ] satisfy repeat1 hide

124+

pair-parser 2seq

125+

[ first ] action repeat0 2seq

126+

[ first2 swap prefix ] action ;

127+128+

: map-parser ( -- parser )

129+

[

130+

"{" token hide , spaces-or-comments optional hide ,

131+

pairs-parser optional ,

132+

spaces-or-comments optional hide , "}" token hide ,

133+

] seq* [ ?first >hashtable ] action ;

134+135+

: set-parser ( -- parser )

136+

[

137+

"#{" token hide , spaces-or-comments optional hide ,

138+

values-parser optional ,

139+

spaces-or-comments optional hide , "}" token hide ,

140+

] seq* [ ?first >hash-set ] action ;

141+142+

: tagged-parser ( -- parser )

143+

[

144+

"#" token hide ,

145+

[ blank? not ] satisfy repeat1 [ >string ] action ,

146+

spaces-or-comments hide ,

147+

value-parser ,

148+

] seq* [ first2 tagged boa ] action ;

149+150+

: value-parser ( -- parser )

151+

[

152+

[

153+

nil-parser ,

154+

boolean-parser ,

155+

string-parser ,

156+

keyword-parser ,

157+

symbol-parser ,

158+

string-parser ,

159+

char-parser ,

160+

float-parser ,

161+

int-parser ,

162+

list-parser ,

163+

vector-parser ,

164+

map-parser ,

165+

set-parser ,

166+

tagged-parser ,

167+

] choice*

168+

] delay ;

169+170+

! XXX: #inst "rfc-3339-format"

171+

! XXX: #uuid "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"

172+173+

PRIVATE>

174+175+

: edn> ( string -- object )

176+

values-parser parse-fully ;

Read the original on github.com ↗