Created
June 29, 2025 14:39
-
-
Save alganet/23df53c567b8a0bf959ecbc7b68997c0 to your computer and use it in GitHub Desktop.
Prototype sh parser written in sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) Alexandre Gomes Gaigalas <[email protected]> | |
# SPDX-License-Identifier: ISC | |
_repeat () { | |
case "${2:-}" in | |
0|"") return;; | |
1) REPLY="$1"; return;; | |
2) REPLY="$1$1"; return;; | |
3) REPLY="$1$1$1"; return;; | |
4) REPLY="$1$1$1$1"; return;; | |
esac | |
local VALUE="$1" COUNT="$2" POW=2; REPLY= | |
while : | |
do | |
if test $POW -gt $COUNT | |
then | |
test $COUNT -gt 0 || break | |
REPLY="$REPLY$VALUE" VALUE="$1" COUNT=$((COUNT - (POW / 2))) POW=2 | |
continue | |
fi | |
VALUE="$VALUE$VALUE" POW=$((POW * 2)) | |
done | |
} | |
_questn () { | |
eval "case \${_questn$1:-} in \"\") _repeat \\? $1; _questn$1=\$REPLY;; esac; REPLY=\$_questn$1"; | |
} | |
alias SINPUTFEED=' | |
if test ${#CODE} -lt 16 -a $# -gt 0 | |
then | |
_a= _b= | |
while test ${#1} -gt 256 | |
do | |
_questn $((${#1} / 2)); | |
_b="${1#${REPLY}}"; _a="${1%$_b}"; shift | |
set -- "$_a" "$_b" "${@:-}" | |
done | |
CODE="$CODE$1" | |
shift | |
fi' | |
alias SINPUTMORE=' | |
if test ${#CODE} -lt 256 -a $# -gt 0 | |
then | |
_a= _b= | |
while test ${#1} -gt 256 | |
do | |
_questn $((${#1} / 2)); | |
_b="${1#${REPLY}}"; _a="${1%$_b}"; shift | |
set -- "$_a" "$_b" "${@:-}" | |
done | |
CODE="$CODE$1" | |
shift | |
fi' | |
alias CONSUME='REST="${CODE#?}"; CONSUMED="$CONSUMED${CODE%"$REST"}"; CODE="$REST"' | |
alias CONSUME2='REST="${CODE#??}"; CONSUMED="$CONSUMED${CODE%"$REST"}"; CODE="$REST"' | |
alias CONSUME3='REST="${CODE#???}"; CONSUMED="$CONSUMED${CODE%"$REST"}"; CODE="$REST"' | |
alias CONSUME4='REST="${CODE#????}"; CONSUMED="$CONSUMED${CODE%"$REST"}"; CODE="$REST"' | |
alias IGNORE='CODE="${CODE#?}"' | |
alias IGNORE2='CODE="${CODE#??}"' | |
alias IGNORE_WS='CODE="${CODE#"${CODE%%[!$_TAB\ ]*}"}"' | |
alias IGNORE_WSE='CODE="${CODE#"${CODE%%[!$_TAB$_EOL\ ]*}"}"' | |
alias SNEW=' | |
STATES="$STATES $STATE"; V=$((V + 1)) | |
case "$CONSUMED" in "");; *) local V$V="$CONSUMED";;esac | |
CONSUMED=' | |
alias SOPEN=' | |
local X$V$STATE="" | |
PARN="${NODES##*" "}" | |
NODE="X$V$STATE"; NODES="$NODES $NODE"' | |
alias SDOWN=' | |
STATE="${STATES##*" "}"; STATES="${STATES%" ${STATE}"}" | |
eval local V$V=\"\${CONSUMED:-\${V$V:-}}\" | |
PARN="${NODES##*" "}" | |
NODE="$PARN"; NODES="${NODES%" $NODE"}"; PARN="${NODES##*" "}"' | |
alias SDISC='SDOWN;unset $NODE' | |
alias SCLOSE='SDOWN;eval "$PARN=\"\$$PARN \$NODE\""' | |
alias SCLOSRNE='SCLOSE; eval "eval \"case \\$\${$NODE#?}\" in \\\"\\\"\) _error $E \;\; esac; E=;"' | |
alias SCLOSOP=' | |
SDOWN | |
eval "case \${$PARN##*" "} in X*) SIBL=\"\${$PARN##*" "}\";; *)SIBL=;;esac" | |
case $SIBL in | |
*BP) eval "$PARN=\"\${$PARN%\" \$SIBL\"}\" $SIBL=\"\${$PARN##*\" \"} \$NODE\" $PARN=\"\${$PARN%\" \"*} \$SIBL\"";; | |
*UP) eval "$PARN=\"\${$PARN%\" \$SIBL\"}\" $SIBL=\"\$NODE\" $PARN=\"\${$PARN%\" \"*} \$SIBL\"";; | |
*) eval "$PARN=\"\$$PARN \$NODE\"";; | |
esac' | |
xxx () { | |
local CODE= STATE=prog I=0 V=0 CONSUMED= NODES=" X0prog" X0prog='' X=0 NODE= REST= PARN= SIBL= E= _a= _b= STATES= | |
# set -- "! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;" | |
# set -- "! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;! foo; zaaa | baz b a c ||$_EOL lo_greatest_name_bar_that_has_ever_been_hooooohaaaaa=a thequickbrownfox && lazydog > foo 2>&1;" | |
# set -- "{ true;};2>&1" | |
set -- "foo && bar" | |
while : $CONSUMED -- x$CODE -- $STATE -- $I | |
do | |
SINPUTFEED | |
case $CODE in | |
'&&'* | '||'*) | |
case $STATE in | |
full) SNEW;STATE=logicBP;SOPEN;CONSUME2;; | |
stmt|exec|cmd) SCLOSOP;; | |
arg|word) SCLOSE;; | |
*) _error LOGIC;;esac;; | |
'!'*) | |
case $STATE in | |
stmt) SNEW;STATE=bangUP;SOPEN;IGNORE;CONSUMED=\!;; | |
arg) SNEW;STATE=word;SOPEN;IGNORE;CONSUMED=\!;; | |
bangUP) IGNORE;CONSUMED=\!;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
cmd) SNEW;STATE=arg;SOPEN;; | |
exec) SCLOSOP;; | |
logicBP) SCLOSE;; | |
*) _error BANG;;esac;; | |
'|'*) | |
case $STATE in | |
exec) SNEW;STATE=pipeBP;SOPEN;IGNORE;CONSUMED=\|;; | |
cpatt) | |
IGNORE;SCLOSE;SNEW;STATE=cpatt;SOPEN;; | |
cmd) SCLOSOP;; | |
arg|word) SCLOSE;; | |
*) _error PIPE;;esac;; | |
"$_EOL"*) | |
case $STATE in | |
logicBP|pipeBP|prog) IGNORE_WSE;; | |
fredir) E=FREDIR; SCLOSRNE;; | |
full) SCLOSE;; | |
stmt|exec) SCLOSOP;; | |
cmd) SCLOSOP;CONSUMED=;; | |
cmdpre|blockpos|arg|word) SCLOSE;CONSUMED=;; | |
commt) SCLOSE;; | |
*) _error END OF LINE;;esac;; | |
';'*) | |
case $STATE in | |
full) SCLOSE;IGNORE;CONSUMED=;; | |
ccasepatt) SCLOSE;SCLOSE;IGNORE;; | |
prog) | |
SCLOSE | |
case $PARN in *ccaseitem) SCLOSE;SCLOSE;IGNORE;;esac | |
;; | |
fredir) E=FREDIR; SCLOSRNE;; | |
stmt|exec|cmd) SCLOSOP;; | |
cmdpre|blockpos|arg|word) SCLOSE;; | |
*) _error SEMICOLON;;esac;; | |
"") | |
case $STATE in | |
prog) break;; | |
fredir) E=FREDIR; SCLOSRNE;; | |
stmt|exec|cmd) SCLOSOP;; | |
blockpos|full|cmdpre|vassig|cmd|arg|word|commt) SCLOSE;; | |
logicBP) _error END LOGIC;; | |
pipeBP) _error END PIPE;; | |
*) _error END OF SCRIPT;;esac;; | |
' '*|"$_TAB"*) | |
case $STATE in | |
ccase|fdecl|blockpos|vassig|cmdpre|cmd|stmt|prog) IGNORE_WS;; | |
exec|bangUP|logicBP|pipeBP) IGNORE_WSE;; | |
fredir) E=FREDIR; SCLOSRNE;; | |
arg|word|expan) SCLOSE;CONSUMED=;; | |
text) CONSUME;; | |
dquo) | |
_error $STATE;; | |
commt) | |
CONSUME;; | |
*) _error ARGUMENT;;esac;; | |
[0-9]'>&'[0-9]*) | |
case $STATE in | |
blockpos|cmdpre|cmd) SNEW;STATE=ioredir;SOPEN;CONSUME4;SCLOSE;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
exec) SNEW;STATE=cmd;SOPEN;STATE=cmdpre;; | |
vassig|arg|word) SCLOSE;; | |
*) _error IOREDIR;;esac;; | |
'>&'[0-9]*) | |
case $STATE in | |
blockpos|cmdpre|cmd) SNEW;STATE=ioredir;SOPEN;CONSUME3;SCLOSE;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
exec) SNEW;STATE=cmd;SOPEN;STATE=cmdpre;; | |
vassig|arg|word) SCLOSE;; | |
*) _error IOREDIR;;esac;; | |
[0-9]'>'*) | |
case $STATE in | |
blockpos|cmdpre|cmd) SNEW;STATE=fredir;SOPEN;CONSUME2;IGNORE_WS;SNEW;STATE=arg;SOPEN;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
exec) SNEW;STATE=cmd;SOPEN;STATE=cmdpre;; | |
vassig|arg|word) SCLOSE;; | |
*) _error FREDIR;;esac;; | |
'>'*) | |
case $STATE in | |
blockpos|cmdpre|cmd) SNEW;STATE=fredir;SOPEN;CONSUME;IGNORE_WS;SNEW;STATE=arg;SOPEN;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
exec) SNEW;STATE=cmd;SOPEN;STATE=cmdpre;; | |
vassig|arg|word) SCLOSE;; | |
*) _error FREDIR;;esac;; | |
"{ "* | "{$_TAB"* | "{$_EOL"*) | |
case $STATE in | |
exec) SNEW;STATE=cmd;SOPEN;SNEW;STATE=block;SOPEN;IGNORE2;SNEW;STATE=prog;SOPEN;; | |
fdecl) SNEW;STATE=block;SOPEN;IGNORE2;SNEW;STATE=prog;SOPEN;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
word) CONSUME;; | |
esac;; | |
'}'*) | |
case $STATE in | |
prog) | |
SCLOSE | |
case $PARN in *block);; *) _error AJDNKAJND;;esac | |
IGNORE;SCLOSE;STATE=blockpos | |
case $CODE in | |
"$_EOL"* | "$_TAB"* | ' '*);; | |
""|';'*);; | |
*) _error BLOCK CLOSING;; | |
esac | |
;; | |
expan|vsubst) SCLOSE; IGNORE;; | |
cmd|exec|arg|word) SCLOSE;; | |
stmt) _error BLOCK CLOSING;; | |
word) CONSUME;; | |
*) _error brclos;;esac;; | |
# escapes | |
# & | |
# until | |
# comments DONE | |
# subshell DONE | |
# dquotesub DONE | |
# expansions DONE (:- :+ %% ## # %) | |
# dquote PARTIAL (dquotesub, escapes) | |
# squote (mostly) DONE (improve chars) | |
# case -- (mostly) DONE (improve errors) | |
# for ------ (mostly) DONE (improve in) | |
# while --- DONE | |
# if --- DONE | |
')'*) | |
case $STATE in | |
word|arg|cmd|exec|stmt|full) SCLOSE;; | |
prog) | |
SCLOSE | |
case $PARN in | |
*dquotesub) | |
IGNORE;SCLOSE;CONSUMED= | |
case $PARN in | |
*dquo) SNEW;STATE=text;SOPEN;; | |
*arg) SCLOSE;; | |
*) _error $PARN AJDNKAJaaaND;; | |
esac;; | |
*subsh) | |
IGNORE;SCLOSE;CONSUMED= | |
case $PARN in | |
*arg) SCLOSE;; | |
*) _error $PARN ---AJDNKAJaaaND;; | |
esac;; | |
*) _error AJDNKAJND;; | |
esac | |
;; | |
cpatt) SCLOSE;IGNORE; | |
SNEW;STATE=prog;SOPEN;; | |
cpatt) IGNORE;SCLOSE;; | |
*) _error CASE ITEMx;;esac;; | |
"'"*) | |
case $STATE in | |
cmd) SNEW;STATE=arg;SOPEN;SNEW;STATE=squo;SOPEN;SNEW;STATE=text;SOPEN;IGNORE;; | |
squo) SCLOSE;IGNORE;; | |
text) SCLOSE;; | |
*) _error squo $STATE;;esac;; | |
'"'*) | |
case $STATE in | |
cmd) SNEW;STATE=arg;SOPEN;SNEW;STATE=dquo;SOPEN;SNEW;STATE=text;SOPEN;IGNORE;; | |
dquo) SCLOSE;IGNORE;; | |
text) SCLOSE;; | |
*) _error dquo $STATE;;esac;; | |
'${'*) | |
case $STATE in | |
cmd) SNEW;STATE=arg;SOPEN;SNEW;STATE=expan;SOPEN;SNEW;STATE=vparam;SOPEN;IGNORE2;; | |
*) _error brop $STATE;;esac;; | |
'$('*) | |
case $STATE in | |
text) | |
SCLOSE | |
case $PARN in *dquo);; *) _error AJDNKAJND;;esac | |
IGNORE2;CONSUMED=;SNEW;STATE=dquotesub;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
cmd) SNEW;STATE=arg;SOPEN;SNEW;STATE=dquotesub;SOPEN;SNEW;STATE=prog;SOPEN;IGNORE2;; | |
*) _error brop $STATE;;esac;; | |
'('*) | |
case $STATE in | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
exec) SNEW;STATE=cmd;SOPEN;; | |
cmd) SNEW;STATE=arg;SOPEN;SNEW;STATE=subsh;SOPEN;SNEW;STATE=prog;SOPEN;IGNORE;; | |
*) _error bropa $STATE;;esac;; | |
'$'*) | |
case $STATE in | |
cmd) SNEW;STATE=arg;SOPEN;SNEW;STATE=expan;SOPEN;SNEW;STATE=vname;SOPEN;IGNORE;; | |
*) _error dquo $STATE;;esac;; | |
':-'* | ':+'* | '%%'* | '##'*) | |
case $STATE in | |
expan) SNEW;STATE=vsubst;SOPEN;CONSUME2;SNEW;STATE=arg;SOPEN;; | |
*) _error col $STATE;;esac;; | |
'#'* | '%'*) | |
case $STATE in | |
expan) SNEW;STATE=vsubst;SOPEN;CONSUME;SNEW;STATE=arg;SOPEN;; | |
prog|cmd) SNEW;STATE=commt;SOPEN;CONSUME;; | |
*) _error col $STATE;;esac;; | |
[a-zA-Z0-9_=]*) | |
case $STATE in | |
word) CONSUME;; | |
vsubst|vparam|vname) | |
SINPUTMORE | |
CONSUMED="${CODE%%[!a-zA-Z0-9_=]*}"; CODE="${CODE#"$CONSUMED"}" | |
SCLOSE; | |
;; | |
execpre) | |
STATE=cmdpre | |
SINPUTMORE | |
MATCH="${CODE%%[!a-zA-Z0-9_=]*}"; REST="${CODE#"$MATCH"}" | |
MATCH2="${REST#"${REST%%[!$_TAB\ ]*}"}" | |
case $MATCH2 in | |
'()'*) | |
CODE="${MATCH2#'()'}" | |
CONSUMED="$MATCH";SNEW;STATE=fdecl;SOPEN; | |
;; | |
*) | |
case $MATCH in | |
'if') | |
CODE="${MATCH2}" | |
CONSUMED="$MATCH";SNEW;STATE=cif;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
'then') | |
SDISC;SCLOSE;SCLOSE;SDISC | |
case $STATES in "") _error kdnafkandkasd;;esac | |
SCLOSE | |
case $PARN in | |
*cif|*celif) | |
CONSUME4;SNEW;STATE=cthen;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
*) _error aijndkjandlaksalallll;; | |
esac;; | |
'elif') | |
SDISC;SCLOSE;SCLOSE;SDISC | |
case $STATES in "") _error zzzzzzzzzzzz;;esac | |
SCLOSE;SCLOSE | |
case $PARN in | |
*cif|*celif) | |
CONSUME4;SNEW;STATE=celif;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
*) _error gggggggg;; | |
esac;; | |
'else') | |
SDISC;SCLOSE;SCLOSE;SDISC | |
case $STATES in "") _error xxxxxxxxxxkdnafkandkasd;;esac | |
SCLOSE;SCLOSE | |
case $PARN in | |
*cif|*celif) | |
CONSUME4;SNEW;STATE=celse;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
*) _error xxxxxxxxxaijndkjandlaksalallll;; | |
esac;; | |
'fi') | |
SDISC;SDISC;SDISC;SDISC | |
case $STATES in "") _error xxxxxxxxxxkdnafkandkasd;;esac | |
SCLOSE;SCLOSE | |
case $PARN in | |
*cif|*celif) | |
CONSUME2;SCLOSE;SCLOSE | |
;; | |
*) _error sadasdaijndkjandlaksalallll;; | |
esac;; | |
'while') | |
CODE="${MATCH2}" | |
CONSUMED="$MATCH";SNEW;STATE=cwhile;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
'for') | |
CODE="${MATCH2}" | |
CONSUMED="$MATCH";SNEW;STATE=cfor;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
'do') | |
SDISC;SCLOSE;SCLOSE;SDISC | |
case $STATES in "") _error kdnafkandkasd;;esac | |
SCLOSE | |
case $PARN in | |
*cwhile|*cfor) | |
CONSUME2;SNEW;STATE=cdo;SOPEN;SNEW;STATE=prog;SOPEN; | |
;; | |
*) _error doinqwkjnkqjwn;; | |
esac;; | |
'done') | |
SDISC;SDISC;SDISC;SDISC | |
case $STATES in "") _error xxxxxxxxxxkdnafkandkasd;;esac | |
SCLOSE;SCLOSE | |
case $PARN in | |
*cwhile|*cfor) | |
CONSUME4;SCLOSE;SCLOSE | |
;; | |
*) _error sadasdaijndkjandlaksalallll;; | |
esac;; | |
'case') | |
CODE="${MATCH2}" | |
CONSUMED="$MATCH";SNEW;STATE=cswitch;SOPEN; | |
;; | |
esac | |
esac | |
;; | |
cswitch) | |
SINPUTMORE | |
MATCH="${CODE%%[!a-zA-Z0-9_]*}"; REST="${CODE#"$MATCH"}" | |
MATCH2="${REST#"${REST%%[!$_TAB\ ]*}"}" | |
case $MATCH2 in | |
'in'*) CODE="${MATCH2#"in"}";CONSUMED="$MATCH";IGNORE_WS;SNEW;STATE=arg;SOPEN;SCLOSE;STATE=ccase;; | |
*) _error CASE;; | |
esac | |
;; | |
ccase) | |
SINPUTMORE | |
MATCH="${CODE%%[!a-zA-Z0-9_]*}"; REST="${CODE#"$MATCH"}" | |
case $MATCH in | |
'esac') CONSUME4;CONSUMED=;SCLOSE;; | |
*) SNEW;STATE=ccaseitem;SOPEN;SNEW;STATE=ccasepatt;SOPEN;; | |
esac | |
;; | |
cmdpre) | |
SINPUTMORE | |
MATCH="${CODE%%[!a-zA-Z0-9_]*}"; REST="${CODE#"$MATCH"}" | |
case $REST in | |
'='*) CODE="$REST";CONSUMED="$MATCH";SNEW;STATE=vassig;SOPEN;SNEW;STATE=arg;SOPEN;IGNORE;CONSUMED=;; | |
*) STATE=cmd;; | |
esac | |
;; | |
vassig) | |
SINPUTMORE | |
MATCH="${CODE%%[!a-zA-Z0-9_]*}"; REST="${CODE#"$MATCH"}" | |
case $REST in | |
'='*) SCLOSE;CODE="$REST";CONSUMED="$MATCH";SNEW;STATE=vassig;SOPEN;SNEW;STATE=arg;SOPEN;IGNORE;CONSUMED=;; | |
*) SCLOSE;STATE=cmd;; | |
esac | |
;; | |
prog) SNEW;STATE=full;SOPEN;; | |
full) SNEW;STATE=stmt;SOPEN;; | |
stmt) SNEW;STATE=exec;SOPEN;; | |
exec) SNEW;STATE=cmd;SOPEN;STATE=execpre;; | |
cmd) SNEW;STATE=arg;SOPEN;; | |
ccasepatt) SNEW;STATE=cpatt;SOPEN;; | |
arg) SNEW;STATE=word;SOPEN;; | |
cpatt) CONSUME;; | |
text|commt) CONSUME;; | |
bangUP|logicBP|pipeBP) SCLOSE;CONSUMED=;; | |
*) _error NAME;;esac;; | |
*) _error CHARACTER;; | |
esac | |
done | |
case $- in *z*);;*) | |
set | while read -r LINE || test -n "$LINE" | |
do | |
case $LINE in | |
[VX][0-9]*) | |
NAM="${LINE%%=*}" | |
eval "VAL=\"\${$NAM:-}\"" | |
_printr1 "$NAM=$VAL" | |
;; | |
esac | |
done | |
exit $? | |
esac | |
} | |
main () { | |
xxx | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Beware, this is a very early stage prototype, with lots of tests missing.
This was an attempt to gain performance using
alias
in shells that support it.Now that I know it works, I can write a much more sensible parser without the
alias
tricks and transpile/inline functions by using the parser itself, so this code will be rewritten.Since I've done it outside of any repo, I'm registering it here as an artifact.