Skip to content

Instantly share code, notes, and snippets.

@mcint
Last active July 19, 2023 23:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcint/8a589500c44d4dc08dcb09b80882c2fd to your computer and use it in GitHub Desktop.
Save mcint/8a589500c44d4dc08dcb09b80882c2fd to your computer and use it in GitHub Desktop.
Minimal parser and interpreter
#!/usr/bin/env bash
: ${DEBUG:=} # 0 ... 2
shopt -s extglob
debug(){ if [[ $DEBUG -ge $1 ]]; then shift 1; eval "${@}"; fi; }
debug 2 shopt -p extglob
acceptArg () {
local spec="$1" cb="$2" arg="$3";
declare -A status=([args]=$(($# < 3)) [matched]=0);
shift 3;
# https://unix.stackexchange.com/a/234415/61350 # how-can-i-use-a-variable-as-a-case-condition
matcher="@($spec)"
case "$arg" in
$matcher) status[matched]=1; eval $cb ;;
*) debug 1 echo "spec: '$spec' failed to match arg: '$arg'";;
esac
debug 2 declare -p status
(( status[matched] ))
return $?
}
count=0
incr(){ echo "$((++count)) $1"; }
handleFirst(){ incr first; }
handleSecond(){ incr second; }
acceptArg "f|first" handleFirst "$1" && shift 1;
acceptArg "s|second|*2" handleSecond "$1" && shift 1;
[[ $? ]] && echo done || echo failed
@mcint
Copy link
Author

mcint commented Jul 19, 2023

I'm writing a bit at odds with bash convention here.
Re: DEBUG, [[ <unset> ]] is false. status[matched]=1, and then checking == 1

Rather bash has 2 conflicting conventions, (( <non-zero> )) -> 0, [[ <zero/null/undef/empty-string> ]] -> 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment