aboutsummaryrefslogtreecommitdiff
path: root/make/reader.mk
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-03-24 16:32:24 -0500
committerJoel Martin <github@martintribe.org>2014-03-24 16:32:24 -0500
commit3169070063b2cb877200117ebb384269d73bcb93 (patch)
tree23de3db1ea5c37afd21a45b6ed7771f56a08c0c4 /make/reader.mk
downloadmal-3169070063b2cb877200117ebb384269d73bcb93.tar.gz
mal-3169070063b2cb877200117ebb384269d73bcb93.zip
Current state of mal for Clojure West lighting talk.
Diffstat (limited to 'make/reader.mk')
-rwxr-xr-xmake/reader.mk170
1 files changed, 170 insertions, 0 deletions
diff --git a/make/reader.mk b/make/reader.mk
new file mode 100755
index 0000000..ce3b078
--- /dev/null
+++ b/make/reader.mk
@@ -0,0 +1,170 @@
+#
+# mal (Make Lisp) Parser/Reader
+#
+
+ifndef __mal_reader_included
+__mal_reader_included := true
+
+_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
+include $(_TOP_DIR)util.mk
+include $(_TOP_DIR)types.mk
+include $(_TOP_DIR)readline.mk
+
+READER_DEBUG ?=
+
+_TOKEN_DELIMS := $(SEMI) $(COMMA) $(DQUOTE) $(QQUOTE) $(_SP) $(_NL) $(_LC) $(_RC) $(_LP) $(_RP) $(LBRACKET) $(RBRACKET)
+
+define READ_NUMBER
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(ch),\
+ $(if $(filter $(_TOKEN_DELIMS),$(ch)),\
+ ,\
+ $(if $(filter-out $(NUMBERS),$(ch)),\
+ $(call _error,Invalid number character '$(ch)'),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(and $(READER_DEBUG),$(info READ_NUMBER ch: $(ch) | $($(1))))\
+ $(ch)$(strip $(call READ_NUMBER,$(1))))),\
+ ))
+endef
+
+define READ_STRING
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(ch),\
+ $(if $(and $(filter \,$(ch)),$(filter $(DQUOTE),$(word 2,$($(1))))),\
+ $(eval $(1) := $(wordlist 3,$(words $($(1))),$($(1))))\
+ $(and $(READER_DEBUG),$(info READ_STRING ch: \$(word 1,$($(1))) | $($(1))))\
+ $(DQUOTE) $(strip $(call READ_STRING,$(1))),\
+ $(if $(filter $(DQUOTE),$(ch)),\
+ ,\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(and $(READER_DEBUG),$(info READ_STRING ch: $(ch) | $($(1))))\
+ $(ch) $(strip $(call READ_STRING,$(1))))),))
+endef
+
+define READ_SYMBOL
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(ch),\
+ $(if $(filter $(_TOKEN_DELIMS),$(ch)),\
+ ,\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(and $(READER_DEBUG),$(info READ_SYMBOL ch: $(ch) | $($(1))))\
+ $(ch)$(strip $(call READ_SYMBOL,$(1)))),\
+ ))
+endef
+
+define READ_ATOM
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(filter $(NUMBERS),$(ch)),\
+ $(call number,$(call READ_NUMBER,$(1))),\
+ $(if $(filter $(DQUOTE),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call _string,$(strip $(call READ_STRING,$(1))))\
+ $(eval $(if $(filter $(DQUOTE),$(word 1,$($(1)))),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\
+ $(call _error,Expected '$(DQUOTE)' in; $($(1))))),\
+ $(foreach sym,$(call READ_SYMBOL,$(1)),\
+ $(if $(call _EQ,nil,$(sym)),\
+ $(__nil),\
+ $(if $(call _EQ,true,$(sym)),\
+ $(__true),\
+ $(if $(call _EQ,false,$(sym)),\
+ $(__false),\
+ $(call symbol,$(sym)))))))))
+endef
+
+# read and return tokens until $(2) found
+define READ_UNTIL
+$(and $(READER_DEBUG),$(info READ_UNTIL: $($(1)) [$(2) $(3)]))
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(ch),\
+ $(if $(filter $(2),$(ch)),\
+ ,\
+ $(call READ_FORM,$(1))\
+ $(call READ_UNTIL,$(1),$(2),$(3))),\
+ $(call _error,Expected '$(3)')))
+endef
+
+define DROP_UNTIL
+$(and $(READER_DEBUG),$(info DROP_UNTIL: $($(1)) [$(2)]))
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(ch),\
+ $(if $(filter $(2),$(ch)),\
+ ,\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call DROP_UNTIL,$(1),$(2),$(3))),\
+ ))
+endef
+
+define READ_SPACES
+$(and $(READER_DEBUG),$(info READ_SPACES: $($(1))))
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(filter $(_SP) $(_NL) $(COMMA),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call READ_SPACES,$(1)),))
+endef
+
+define READ_FORM
+$(and $(READER_DEBUG),$(info READ_FORM: $($(1))))
+$(call READ_SPACES,$(1))
+$(foreach ch,$(word 1,$($(1))),\
+ $(if $(filter $(SEMI),$(ch)),\
+ $(call DROP_UNTIL,$(1),$(_NL)),\
+ $(if $(filter $(SQUOTE),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call list,$(call symbol,quote) $(strip $(call READ_FORM,$(1)))),\
+ $(if $(filter $(QQUOTE),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call list,$(call symbol,quasiquote) $(strip $(call READ_FORM,$(1)))),\
+ $(if $(filter $(UNQUOTE),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call list,$(call symbol,unquote) $(strip $(call READ_FORM,$(1)))),\
+ $(if $(filter $(_SUQ),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call list,$(call symbol,splice-unquote) $(strip $(call READ_FORM,$(1)))),\
+ $(if $(filter $(CARET),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(foreach meta,$(strip $(call READ_FORM,$(1))),\
+ $(call list,$(call symbol,with-meta) $(strip $(call READ_FORM,$(1))) $(meta))),\
+ $(if $(filter $(ATSIGN),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(call list,$(call symbol,deref) $(strip $(call READ_FORM,$(1)))),\
+ $(if $(filter $(_RC),$(ch)),\
+ $(call _error,Unexpected '$(RCURLY)'),\
+ $(if $(filter $(_LC),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(foreach thm,$(call hash_map),\
+ $(call do,$(call _assoc_seq!,$(thm),$(strip $(call READ_UNTIL,$(1),$(_RC),$(RCURLY)))))\
+ $(eval $(if $(filter $(_RC),$(word 1,$($(1)))),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\
+ $(call _error,Expected '$(RCURLY)')))\
+ $(thm)),\
+ $(if $(filter $(_RP),$(ch)),\
+ $(call _error,Unexpected '$(RPAREN)'),\
+ $(if $(filter $(_LP),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(foreach tlist,$(call _list),\
+ $(eval $(foreach item,$(strip $(call READ_UNTIL,$(1),$(_RP),$(RPAREN))),\
+ $(call do,$(call _conj!,$(tlist),$(item)))))\
+ $(eval $(if $(filter $(_RP),$(word 1,$($(1)))),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\
+ $(call _error,Expected '$(RPAREN)')))\
+ $(tlist)),\
+ $(if $(filter $(RBRACKET),$(ch)),\
+ $(call _error,Unexpected '$(RBRACKET)'),\
+ $(if $(filter $(LBRACKET),$(ch)),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
+ $(foreach tvec,$(call _vector),\
+ $(eval $(foreach item,$(strip $(call READ_UNTIL,$(1),$(RBRACKET),$(RBRACKET))),\
+ $(call do,$(call _conj!,$(tvec),$(item)))))\
+ $(eval $(if $(filter $(RBRACKET),$(word 1,$($(1)))),\
+ $(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\
+ $(call _error,Expected '$(RBRACKET)')))\
+ $(tvec)),\
+ $(call READ_ATOM,$(1))))))))))))))))
+$(call READ_SPACES,$(1))
+endef
+
+# read-str from a raw "string" or from a string object
+READ_STR = $(strip $(eval __reader_temp := $(call str_encode,$(if $(call _string?,$(1)),$(call str_decode,$($(1)_value)),$(1))))$(call READ_FORM,__reader_temp))
+
+endif