From 5f1a136992dd5882d44e16de8955cb9947e86927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Georges=20Dup=C3=A9ron?= Date: Thu, 28 Feb 2019 00:00:50 +0100 Subject: [PATCH] Simple lexer for micro-scheme --- micro-scheme/micro-scheme.sh | 83 ++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 micro-scheme/micro-scheme.sh diff --git a/micro-scheme/micro-scheme.sh b/micro-scheme/micro-scheme.sh new file mode 100755 index 0000000..ea2a9c5 --- /dev/null +++ b/micro-scheme/micro-scheme.sh @@ -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 +)