Commit | Line | Data |
---|---|---|
31690700 JM |
1 | # |
2 | # mal (Make Lisp) Parser/Reader | |
3 | # | |
4 | ||
ea81a808 JM |
5 | if [ -z "${__mal_readerr_included__}" ]; then |
6 | __mal_readerr_included=true | |
7 | ||
31690700 JM |
8 | source $(dirname $0)/types.sh |
9 | ||
10 | READ_ATOM () { | |
11 | local token=${__reader_tokens[${__reader_idx}]} | |
12 | __reader_idx=$(( __reader_idx + 1 )) | |
13 | case "${token}" in | |
a61be4d3 JM |
14 | [0-9]*) _number "${token}" ;; |
15 | -[0-9]*) _number "${token}" ;; | |
4ad84d24 | 16 | \"*) if [[ ! "${token}" =~ ^\"(\\.|[^\\\"])*\"$ ]]; then |
970935da JM |
17 | _error "expected '\"', got EOF" |
18 | return | |
19 | fi | |
20 | token="${token:1:-1}" | |
ea02f464 | 21 | token="${token//\\\\/${__keyw}}" |
31690700 | 22 | token="${token//\\\"/\"}" |
8d78bc26 | 23 | token="${token//\\n/$'\n'}" |
ea02f464 | 24 | token="${token//${__keyw}/\\}" |
ea81a808 | 25 | _string "${token}" ;; |
b8ee29b2 | 26 | :*) _keyword "${token:1}" ;; |
31690700 JM |
27 | nil) r="${__nil}" ;; |
28 | true) r="${__true}" ;; | |
29 | false) r="${__false}" ;; | |
ea81a808 | 30 | *) _symbol "${token}" ;; |
31690700 JM |
31 | esac |
32 | } | |
33 | ||
34 | # Return seqence of tokens into r. | |
35 | # ${1}: Type of r (vector, list) | |
36 | # ${2}: starting symbol | |
37 | # ${3}: ending symbol | |
38 | READ_SEQ () { | |
39 | local start="${1}" | |
40 | local end="${2}" | |
41 | local items="" | |
42 | local token=${__reader_tokens[${__reader_idx}]} | |
43 | __reader_idx=$(( __reader_idx + 1 )) | |
44 | if [[ "${token}" != "${start}" ]]; then | |
45 | r= | |
46 | _error "expected '${start}'" | |
47 | return | |
48 | fi | |
49 | token=${__reader_tokens[${__reader_idx}]} | |
50 | while [[ "${token}" != "${end}" ]]; do | |
51 | if [[ ! "${token}" ]]; then | |
52 | r= | |
970935da | 53 | _error "expected '${end}', got EOF" |
31690700 JM |
54 | return |
55 | fi | |
56 | READ_FORM | |
57 | items="${items} ${r}" | |
58 | token=${__reader_tokens[${__reader_idx}]} | |
59 | done | |
60 | __reader_idx=$(( __reader_idx + 1 )) | |
61 | r="${items:1}" | |
62 | } | |
63 | ||
64 | # Return form in r | |
65 | READ_FORM () { | |
66 | local token=${__reader_tokens[${__reader_idx}]} | |
67 | case "${token}" in | |
68 | \') __reader_idx=$(( __reader_idx + 1 )) | |
ea81a808 | 69 | _symbol quote; local q="${r}" |
31690700 | 70 | READ_FORM; local f="${r}" |
ea81a808 | 71 | _list "${q}" "${f}" ;; |
31690700 | 72 | \`) __reader_idx=$(( __reader_idx + 1 )) |
ea81a808 | 73 | _symbol quasiquote; local q="${r}" |
31690700 | 74 | READ_FORM; local f="${r}" |
ea81a808 | 75 | _list "${q}" "${f}" ;; |
31690700 | 76 | \~) __reader_idx=$(( __reader_idx + 1 )) |
ea81a808 | 77 | _symbol unquote; local q="${r}" |
31690700 | 78 | READ_FORM; local f="${r}" |
ea81a808 | 79 | _list "${q}" "${f}" ;; |
31690700 | 80 | \~\@) __reader_idx=$(( __reader_idx + 1 )) |
ea81a808 | 81 | _symbol splice-unquote; local q="${r}" |
31690700 | 82 | READ_FORM; local f="${r}" |
ea81a808 | 83 | _list "${q}" "${f}" ;; |
31690700 | 84 | ^) __reader_idx=$(( __reader_idx + 1 )) |
ea81a808 | 85 | _symbol with-meta; local wm="${r}" |
31690700 JM |
86 | READ_FORM; local meta="${r}" |
87 | READ_FORM; local obj="${r}" | |
ea81a808 | 88 | _list "${wm}" "${obj}" "${meta}" ;; |
31690700 | 89 | @) __reader_idx=$(( __reader_idx + 1 )) |
ea81a808 | 90 | _symbol deref; local d="${r}" |
31690700 | 91 | READ_FORM; local f="${r}" |
ea81a808 | 92 | _list "${d}" "${f}" ;; |
31690700 JM |
93 | \)) _error "unexpected ')'" ;; |
94 | \() READ_SEQ "(" ")" | |
ea81a808 | 95 | _list ${r} ;; |
31690700 JM |
96 | \]) _error "unexpected ']'" ;; |
97 | \[) READ_SEQ "[" "]" | |
ea81a808 | 98 | _vector ${r} ;; |
31690700 JM |
99 | \}) _error "unexpected '}'" ;; |
100 | \{) READ_SEQ "{" "}" | |
ea81a808 | 101 | _hash_map ${r} ;; |
31690700 JM |
102 | *) READ_ATOM |
103 | esac | |
104 | } | |
105 | ||
106 | # Returns __reader_tokens as an indexed array of tokens | |
107 | TOKENIZE () { | |
108 | local data="${*}" | |
109 | local datalen=${#data} | |
110 | local idx=0 | |
111 | local chunk=0 | |
112 | local chunksz=500 | |
113 | local match= | |
114 | local token= | |
115 | local str= | |
116 | ||
117 | __reader_idx=0 | |
118 | __reader_tokens= | |
119 | while true; do | |
120 | if (( ${#str} < ( chunksz / 2) )) && (( chunk < datalen )); then | |
121 | str="${str}${data:${chunk}:${chunksz}}" | |
122 | chunk=$(( chunk + ${chunksz} )) | |
123 | fi | |
124 | (( ${#str} == 0 )) && break | |
970935da | 125 | [[ "${str}" =~ ^^([][{}\(\)^@])|^(~@)|(\"(\\.|[^\\\"])*\"?)|^(;[^$'\n']*)|^([~\'\`])|^([^][ ~\`\'\";{}\(\)^@\,]+)|^[,]|^[[:space:]]+ ]] |
31690700 JM |
126 | match=${BASH_REMATCH[0]} |
127 | str="${str:${#match}}" | |
128 | token="${match//$'\n'/}" | |
129 | #echo "MATCH: '${token}' / [${str}]" | |
130 | if ! [[ "${token}" =~ (^[,]$|^[[:space:]]*;.*$|^[[:space:]]*$) ]]; then | |
131 | __reader_tokens[${idx}]="${token}" | |
132 | idx=$(( idx + 1 )) | |
133 | fi | |
134 | if [ -z "${match}" ]; then | |
31690700 | 135 | _error "Tokenizing error at: ${str:0:50}" |
70aff0c1 | 136 | return 1 |
31690700 JM |
137 | fi |
138 | done | |
139 | } | |
140 | ||
141 | # read-str from a raw "string" or from a string object. Retruns object | |
142 | # read in r. | |
143 | READ_STR () { | |
144 | declare -a __reader_tokens | |
70aff0c1 | 145 | TOKENIZE "${*}" || return 1 # sets __reader_tokens |
31690700 | 146 | #set | grep ^__reader_tokens |
b8ee29b2 | 147 | if [ -z "${__reader_tokens[0]}" ]; then |
31690700 JM |
148 | r= |
149 | return 1 # No tokens | |
150 | fi | |
151 | READ_FORM | |
152 | #echo "Token: ${r}: <${ANON["${r}"]}>" | |
153 | return | |
154 | } | |
155 | ||
156 | # Call readline and save the history. Returns the string read in r. | |
157 | READLINE_EOF= | |
158 | READLINE_HISTORY_FILE=${HOME}/.mal-history | |
159 | READLINE () { | |
c9de2e82 | 160 | history -r "${READLINE_HISTORY_FILE}" 2>/dev/null || true |
31690700 JM |
161 | read -r -e -p "${1}" r || return "$?" |
162 | history -s -- "${r}" | |
c9de2e82 | 163 | history -a "${READLINE_HISTORY_FILE}" 2>/dev/null || true |
31690700 | 164 | } |
ea81a808 JM |
165 | |
166 | fi |