Commit | Line | Data |
---|---|---|
31690700 JM |
1 | # |
2 | # mal (Make Lisp) Parser/Reader | |
3 | # | |
4 | ||
5 | ifndef __mal_reader_included | |
6 | __mal_reader_included := true | |
7 | ||
8 | _TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST))) | |
9 | include $(_TOP_DIR)util.mk | |
10 | include $(_TOP_DIR)types.mk | |
11 | include $(_TOP_DIR)readline.mk | |
12 | ||
13 | READER_DEBUG ?= | |
14 | ||
15 | _TOKEN_DELIMS := $(SEMI) $(COMMA) $(DQUOTE) $(QQUOTE) $(_SP) $(_NL) $(_LC) $(_RC) $(_LP) $(_RP) $(LBRACKET) $(RBRACKET) | |
16 | ||
17 | define READ_NUMBER | |
18 | $(foreach ch,$(word 1,$($(1))),\ | |
19 | $(if $(ch),\ | |
20 | $(if $(filter $(_TOKEN_DELIMS),$(ch)),\ | |
21 | ,\ | |
4c0073a3 | 22 | $(if $(filter-out $(MINUS) $(NUMBERS),$(ch)),\ |
31690700 JM |
23 | $(call _error,Invalid number character '$(ch)'),\ |
24 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
25 | $(and $(READER_DEBUG),$(info READ_NUMBER ch: $(ch) | $($(1))))\ | |
26 | $(ch)$(strip $(call READ_NUMBER,$(1))))),\ | |
27 | )) | |
28 | endef | |
29 | ||
8d78bc26 JM |
30 | # $(_NL) is used here instead of $(NEWLINE) because $(strip) removes |
31 | # $(NEWLINE). str_encode will just pass through $(_NL) so str_decode | |
32 | # later will restore a correct newline | |
31690700 JM |
33 | define READ_STRING |
34 | $(foreach ch,$(word 1,$($(1))),\ | |
35 | $(if $(ch),\ | |
36 | $(if $(and $(filter \,$(ch)),$(filter $(DQUOTE),$(word 2,$($(1))))),\ | |
37 | $(eval $(1) := $(wordlist 3,$(words $($(1))),$($(1))))\ | |
38 | $(and $(READER_DEBUG),$(info READ_STRING ch: \$(word 1,$($(1))) | $($(1))))\ | |
39 | $(DQUOTE) $(strip $(call READ_STRING,$(1))),\ | |
8d78bc26 JM |
40 | $(if $(and $(filter \,$(ch)),$(filter n,$(word 2,$($(1))))),\ |
41 | $(eval $(1) := $(wordlist 3,$(words $($(1))),$($(1))))\ | |
42 | $(and $(READER_DEBUG),$(info READ_STRING ch: \$(word 1,$($(1))) | $($(1))))\ | |
43 | $(_NL) $(strip $(call READ_STRING,$(1))),\ | |
44 | $(if $(and $(filter \,$(ch)),$(filter \,$(word 2,$($(1))))),\ | |
45 | $(eval $(1) := $(wordlist 3,$(words $($(1))),$($(1))))\ | |
46 | $(and $(READER_DEBUG),$(info READ_STRING ch: \$(word 1,$($(1))) | $($(1))))\ | |
47 | \ $(strip $(call READ_STRING,$(1))),\ | |
31690700 JM |
48 | $(if $(filter $(DQUOTE),$(ch)),\ |
49 | ,\ | |
50 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
51 | $(and $(READER_DEBUG),$(info READ_STRING ch: $(ch) | $($(1))))\ | |
8d78bc26 | 52 | $(ch) $(strip $(call READ_STRING,$(1))))))),)) |
31690700 JM |
53 | endef |
54 | ||
55 | define READ_SYMBOL | |
56 | $(foreach ch,$(word 1,$($(1))),\ | |
57 | $(if $(ch),\ | |
58 | $(if $(filter $(_TOKEN_DELIMS),$(ch)),\ | |
59 | ,\ | |
60 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
61 | $(and $(READER_DEBUG),$(info READ_SYMBOL ch: $(ch) | $($(1))))\ | |
62 | $(ch)$(strip $(call READ_SYMBOL,$(1)))),\ | |
63 | )) | |
64 | endef | |
65 | ||
b8ee29b2 JM |
66 | define READ_KEYWORD |
67 | $(foreach ch,$(word 1,$($(1))),\ | |
68 | $(if $(ch),\ | |
69 | $(if $(filter $(_TOKEN_DELIMS),$(ch)),\ | |
70 | ,\ | |
71 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
72 | $(and $(READER_DEBUG),$(info READ_KEYWORD ch: $(ch) | $($(1))))\ | |
73 | $(ch)$(strip $(call READ_KEYWORD,$(1)))),\ | |
74 | )) | |
75 | endef | |
76 | ||
31690700 | 77 | define READ_ATOM |
b137ff4f | 78 | $(and $(READER_DEBUG),$(info READ_ATOM: $($(1)))) |
31690700 | 79 | $(foreach ch,$(word 1,$($(1))),\ |
4c0073a3 JM |
80 | $(if $(and $(filter $(MINUS),$(ch)),$(filter $(NUMBERS),$(word 2,$($(1))))),\ |
81 | $(call _number,$(call READ_NUMBER,$(1))),\ | |
31690700 | 82 | $(if $(filter $(NUMBERS),$(ch)),\ |
ea81a808 | 83 | $(call _number,$(call READ_NUMBER,$(1))),\ |
31690700 JM |
84 | $(if $(filter $(DQUOTE),$(ch)),\ |
85 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
ea81a808 | 86 | $(call __string,$(strip $(call READ_STRING,$(1))))\ |
31690700 JM |
87 | $(eval $(if $(filter $(DQUOTE),$(word 1,$($(1)))),\ |
88 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\ | |
4aa0ebdf | 89 | $(call _error,Expected '$(DQUOTE)' in; $($(1))$(COMMA) got EOF))),\ |
b8ee29b2 JM |
90 | $(if $(filter $(COLON),$(ch)),\ |
91 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
92 | $(call _keyword,$(call READ_KEYWORD,$(1))),\ | |
31690700 JM |
93 | $(foreach sym,$(call READ_SYMBOL,$(1)),\ |
94 | $(if $(call _EQ,nil,$(sym)),\ | |
95 | $(__nil),\ | |
96 | $(if $(call _EQ,true,$(sym)),\ | |
97 | $(__true),\ | |
98 | $(if $(call _EQ,false,$(sym)),\ | |
99 | $(__false),\ | |
4c0073a3 | 100 | $(call _symbol,$(sym))))))))))) |
31690700 JM |
101 | endef |
102 | ||
103 | # read and return tokens until $(2) found | |
104 | define READ_UNTIL | |
105 | $(and $(READER_DEBUG),$(info READ_UNTIL: $($(1)) [$(2) $(3)])) | |
106 | $(foreach ch,$(word 1,$($(1))),\ | |
107 | $(if $(ch),\ | |
108 | $(if $(filter $(2),$(ch)),\ | |
109 | ,\ | |
110 | $(call READ_FORM,$(1))\ | |
111 | $(call READ_UNTIL,$(1),$(2),$(3))),\ | |
ae6e2220 | 112 | $(call _error,Expected '$(3)'$(COMMA) got EOF))) |
31690700 JM |
113 | endef |
114 | ||
115 | define DROP_UNTIL | |
116 | $(and $(READER_DEBUG),$(info DROP_UNTIL: $($(1)) [$(2)])) | |
117 | $(foreach ch,$(word 1,$($(1))),\ | |
118 | $(if $(ch),\ | |
119 | $(if $(filter $(2),$(ch)),\ | |
120 | ,\ | |
121 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
122 | $(call DROP_UNTIL,$(1),$(2),$(3))),\ | |
123 | )) | |
124 | endef | |
125 | ||
126 | define READ_SPACES | |
127 | $(and $(READER_DEBUG),$(info READ_SPACES: $($(1)))) | |
128 | $(foreach ch,$(word 1,$($(1))),\ | |
129 | $(if $(filter $(_SP) $(_NL) $(COMMA),$(ch)),\ | |
130 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
131 | $(call READ_SPACES,$(1)),)) | |
132 | endef | |
133 | ||
134 | define READ_FORM | |
135 | $(and $(READER_DEBUG),$(info READ_FORM: $($(1)))) | |
136 | $(call READ_SPACES,$(1)) | |
137 | $(foreach ch,$(word 1,$($(1))),\ | |
138 | $(if $(filter $(SEMI),$(ch)),\ | |
139 | $(call DROP_UNTIL,$(1),$(_NL)),\ | |
140 | $(if $(filter $(SQUOTE),$(ch)),\ | |
141 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
ea81a808 | 142 | $(call _list,$(call _symbol,quote) $(strip $(call READ_FORM,$(1)))),\ |
31690700 JM |
143 | $(if $(filter $(QQUOTE),$(ch)),\ |
144 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
ea81a808 | 145 | $(call _list,$(call _symbol,quasiquote) $(strip $(call READ_FORM,$(1)))),\ |
31690700 JM |
146 | $(if $(filter $(UNQUOTE),$(ch)),\ |
147 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
ea81a808 | 148 | $(call _list,$(call _symbol,unquote) $(strip $(call READ_FORM,$(1)))),\ |
31690700 JM |
149 | $(if $(filter $(_SUQ),$(ch)),\ |
150 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
ea81a808 | 151 | $(call _list,$(call _symbol,splice-unquote) $(strip $(call READ_FORM,$(1)))),\ |
31690700 JM |
152 | $(if $(filter $(CARET),$(ch)),\ |
153 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
154 | $(foreach meta,$(strip $(call READ_FORM,$(1))),\ | |
ea81a808 | 155 | $(call _list,$(call _symbol,with-meta) $(strip $(call READ_FORM,$(1))) $(meta))),\ |
31690700 JM |
156 | $(if $(filter $(ATSIGN),$(ch)),\ |
157 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
ea81a808 | 158 | $(call _list,$(call _symbol,deref) $(strip $(call READ_FORM,$(1)))),\ |
31690700 JM |
159 | $(if $(filter $(_RC),$(ch)),\ |
160 | $(call _error,Unexpected '$(RCURLY)'),\ | |
161 | $(if $(filter $(_LC),$(ch)),\ | |
162 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
b137ff4f | 163 | $(call READ_SPACES,$(1))\ |
ea81a808 | 164 | $(foreach thm,$(call _hash_map),\ |
31690700 JM |
165 | $(call do,$(call _assoc_seq!,$(thm),$(strip $(call READ_UNTIL,$(1),$(_RC),$(RCURLY)))))\ |
166 | $(eval $(if $(filter $(_RC),$(word 1,$($(1)))),\ | |
167 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\ | |
ae6e2220 | 168 | $(call _error,Expected '$(RCURLY)'$(COMMA) got EOF)))\ |
31690700 JM |
169 | $(thm)),\ |
170 | $(if $(filter $(_RP),$(ch)),\ | |
171 | $(call _error,Unexpected '$(RPAREN)'),\ | |
172 | $(if $(filter $(_LP),$(ch)),\ | |
173 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
b137ff4f | 174 | $(call READ_SPACES,$(1))\ |
31690700 JM |
175 | $(foreach tlist,$(call _list),\ |
176 | $(eval $(foreach item,$(strip $(call READ_UNTIL,$(1),$(_RP),$(RPAREN))),\ | |
177 | $(call do,$(call _conj!,$(tlist),$(item)))))\ | |
178 | $(eval $(if $(filter $(_RP),$(word 1,$($(1)))),\ | |
179 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\ | |
ae6e2220 | 180 | $(call _error,Expected '$(RPAREN)'$(COMMA) got EOF)))\ |
31690700 JM |
181 | $(tlist)),\ |
182 | $(if $(filter $(RBRACKET),$(ch)),\ | |
183 | $(call _error,Unexpected '$(RBRACKET)'),\ | |
184 | $(if $(filter $(LBRACKET),$(ch)),\ | |
185 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\ | |
b137ff4f | 186 | $(call READ_SPACES,$(1))\ |
31690700 JM |
187 | $(foreach tvec,$(call _vector),\ |
188 | $(eval $(foreach item,$(strip $(call READ_UNTIL,$(1),$(RBRACKET),$(RBRACKET))),\ | |
189 | $(call do,$(call _conj!,$(tvec),$(item)))))\ | |
190 | $(eval $(if $(filter $(RBRACKET),$(word 1,$($(1)))),\ | |
191 | $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\ | |
ae6e2220 | 192 | $(call _error,Expected '$(RBRACKET)'$(COMMA) got EOF)))\ |
31690700 JM |
193 | $(tvec)),\ |
194 | $(call READ_ATOM,$(1)))))))))))))))) | |
195 | $(call READ_SPACES,$(1)) | |
196 | endef | |
197 | ||
198 | # read-str from a raw "string" or from a string object | |
199 | READ_STR = $(strip $(eval __reader_temp := $(call str_encode,$(if $(call _string?,$(1)),$(call str_decode,$($(1)_value)),$(1))))$(call READ_FORM,__reader_temp)) | |
200 | ||
201 | endif |