Simple lexer for micro-scheme

This commit is contained in:
Georges Dupéron 2019-02-28 00:00:50 +01:00
parent a51a05f606
commit 5f1a136992

83
micro-scheme/micro-scheme.sh Executable file
View File

@ -0,0 +1,83 @@
#!/bin/sh
stack_init_name_unit() {
eval "stacklast_${1}="
}
stack_push_name_hex_unit() {
# args: $1 must be an [a-z]+ name
# $2 must be a hexadecimal string
# input: stacklast_$1
# output: stacklast_$1 stack_$1_${!stacklast_$1}
# clobbers: stacklast
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
eval stacklast='${'stacklast_${1}'}'
stacklast=$((${stacklast}+1))
echo stack_${1}_${stacklast}='"'${2}'"'
eval stack_${1}_${stacklast}='"'${2}'"'
eval stacklast_${1}=${stacklast}
}
stack_len_name_int() {
# args: $1 must be an [a-z]+ name
# input: stacklast_$1
# output: stdout=${!stacklast_$1}
# clobbers: nothing
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
eval 'printf %s ${'stacklast_${1}'}'
}
stack_pop_name_result_unit() {
# args: $1 must be an [a-z]+ name
# input: stacklast_$1
# output: stacklast_$1 stack_$1_${!stacklast_$1}
# clobbers: stacklast
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
eval stacklast='${'stacklast_${1}'}'
eval $2'="${'stack_${1}_${stacklast}'}"'
stacklast=$((${stacklast}-1))
eval stacklast_${1}=${stacklast}
}
stack_peek_name_hex() {
# args: $1 must be an [a-z]+ name
# input: stacklast_$1 stack_$1_${!stacklast_$1}
# output: stdout
# clobbers: stacklast
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
eval stacklast='${'stacklast_${1}'}'
eval 'printf %s "${'stack_${1}_${stacklast}'}"'
}
stack_init_name_unit parse_stack
stack_push_name_hex_unit parse ''
printf '(+ 1 ( + 22 345 ))' | \
od -v -A n -t x1 | sed -e 's/^ //' | tr ' ' \\n | (while read c; do
case "$c" in
# Open paren
28) if test "x$(stack_peek_name_hex parse)" = 'x'; then
stack_pop_name_result_unit parse current
fi
stack_push_name_hex_unit parse 28
stack_push_name_hex_unit parse '';;
# Close paren
29) if test "x$(stack_peek_name_hex parse)" = 'x'; then
stack_pop_name_result_unit parse current
fi
stack_push_name_hex_unit parse 29;;
# Space
20) if test "x$(stack_peek_name_hex parse)" != 'x'; then
stack_push_name_hex_unit parse ''
fi;;
# identifier character
*) stack_pop_name_result_unit parse current
stack_push_name_hex_unit parse "$current$c";;
esac
done
while test "x$(stack_len_name_int parse)" != 'x0'; do
stack_pop_name_result_unit parse tmp
echo "$tmp 0a"
done | tac | xxd -ps -r
)