sc= sgetc() { sc="$(dd bs=1 count=1 2>/dev/null; printf '.')" sc="${sc%.}" } toktext() { local t="${1}" shift 1 local n= case "${t%${US}*}" in # Operators T_EOF) n='';; T_NEWLINE) n="${LF}";; T_AND) n='&';; T_SEMI) n=';';; T_AND_IF) n='&&';; T_OR_IF) n='||';; T_DSEMI) n=';;';; T_LESS) n='<';; T_GREAT) n='>';; T_DLESS) n='<<';; T_DGREAT) n='>>';; T_LESS) n='<';; T_LESSAND) n='<&';; T_GREAT) n='>';; T_GREATAND) n='>&';; T_LESSGREAT) n='<>';; T_DLESSDASH) n='<<-';; T_CLOBBER) n='>|';; T_PIPE) n='|';; T_LPAREN) n='(';; T_RPAREN) n=')';; # Reserved words T_IF) n='if';; T_THEN) n='then';; T_ELSE) n='else';; T_ELIF) n='elif';; T_FI) n='fi';; T_DO) n='do';; T_DONE) n='done';; T_CASE) n='case';; T_ESAC) n='esac';; T_WHILE) n='while';; T_UNTIL) n='until';; T_FOR) n='for';; T_LBRACE) n='{';; T_RBRACE) n='}';; T_BANG) n='!';; T_IN) n='in';; # Special symbols T_NAME) n="${t#*${US}}";; T_FNAME) n="${t#*${US}}";; T_CMDNAME) n="${t#*${US}}";; T_IO_NUMBER) n="${t#*${US}}";; T_WORD) n="${t#*${US}}";; T_ASSIGNMENT_WORD) n="${t#*${US}}";; # Unknown *) n='';; esac printf '%s' "${n}" } codegen_sub() { local array="${1}" shift 1 IFS="${RS}" for t in ${array}; do toktext "${t}" case "${t%${US}*}" in T_NEWLINE) ;; *) printf ' ' ;; esac done unset IFS } # The token stack is encoded in a string in the following grammar: # Terminal symbols: # TOKEN # Production rules: # stack = tokens [ '' type '' stack '' [ tokens ] ] ; # tokens = TOKEN { '' TOKEN } ; # type = 'C' ; # We need to recurse through this stack to get to all the tokens. # Each element in the stack (an array of tokens) gets run through the codegen to # become text that is inserted into the array below. parse_stack() { local array= array='' while :; do sgetc case "${sc}" in '') # EOF break ;; "${SOH}") # New stack element sgetc case "${sc}" in 'C') # Command substitution sgetc # STX array="${array}$(parse_stack)." array="${array%.}" ;; esac ;; "${ETX}") # End of stack element break ;; *) # Token character array="${array}${sc}" ;; esac done codegen_sub "${array}" } codegen() { local toks="${1}" shift 1 if printf '%s' "${toks}" | parse_stack; then return 0 else return 1 fi }