diff options
author | P. J. McDermott <pj@pehjota.net> | 2016-02-20 22:59:51 (EST) |
---|---|---|
committer | P. J. McDermott <pj@pehjota.net> | 2016-02-20 22:59:51 (EST) |
commit | 9e2a93ddddeb89aa2512f2c6ee09a740729d9704 (patch) | |
tree | e5f31dcad1d7e50506632dc715951729a049acd9 | |
parent | 292939d65a7ee4ceff225cb9bea671afc837f3b4 (diff) | |
download | eggshell-9e2a93ddddeb89aa2512f2c6ee09a740729d9704.zip eggshell-9e2a93ddddeb89aa2512f2c6ee09a740729d9704.tar.gz eggshell-9e2a93ddddeb89aa2512f2c6ee09a740729d9704.tar.bz2 |
Implement arithmetic expansion
-rw-r--r-- | parsing/lexer.sh | 61 | ||||
-rw-r--r-- | parsing/parse.sh | 16 |
2 files changed, 68 insertions, 9 deletions
diff --git a/parsing/lexer.sh b/parsing/lexer.sh index 924964e..ce39c23 100644 --- a/parsing/lexer.sh +++ b/parsing/lexer.sh @@ -344,8 +344,7 @@ scan_wordexp() case "${c}" in '(') # Arithmetic expansion - synerr 'Arithmetic expansion is %s' \ - 'not yet supported' + scan_wordexp_arith ;; *) # Command substitution @@ -391,7 +390,6 @@ scan_wordexp_param_brace() local param= local word= - ln_off=0 mod=true lgetc @@ -554,6 +552,63 @@ scan_param() return 0 } +scan_wordexp_arith() +{ + local arith= + local paren_lvl= + local res= + local sub_wordexp= + + arith='' + paren_lvl=0 + while :; do + lgetc + case "${c}" in + '') + synerr 'end of file unexpected (%s)' \ + 'expecting "))"' + ;; + '(') + arith="${arith}${c}" + paren_lvl=$((${paren_lvl} + 1)) + ;; + ')') + if [ ${paren_lvl} -eq 0 ]; then + lgetc + case "${c}" in ')') + wordexp="\$((${arith}))" + lgetc + return 0 + ;; + esac + synerr 'Arithmetic expansion: ")" %s' \ + 'unexpected' + fi + arith="${arith}${c}" + paren_lvl=$((${paren_lvl} - 1)) + ;; + '$') + lgetc + if ! res=$(scan_wordexp); then + exit 1 + fi + ln_off=${res%%${RS}*} + res="${res#*${RS}}" + c="${res%%${RS}*}" + res="${res#*${RS}}" + sub_wordexp="${res%%${RS}*}" + # We must advance lineno because scan_wordexp() + # was run in a subshell. + lineno=$((${lineno} + ${ln_off})) + arith="${arith}${sub_wordexp}" + ;; + *) + arith="${arith}${c}" + ;; + esac + done +} + # # Interface # diff --git a/parsing/parse.sh b/parsing/parse.sh index 8f73b32..6508142 100644 --- a/parsing/parse.sh +++ b/parsing/parse.sh @@ -624,12 +624,12 @@ try() } #try '"foo bar" && $baz || qux' '${quux%uux quuux' -try '"foo bar" && $baz || qux' '${quux%uux } quuux' -try 'foo ${bar}' -try 'foo ${#bar}' -try 'foo ${bar#baz}' -try 'foo ${#bar#}' -try 'foo ${^}' +#try '"foo bar" && $baz || qux' '${quux%uux } quuux' +#try 'foo ${bar}' +#try 'foo ${#bar}' +#try 'foo ${bar#baz}' +#try 'foo ${#bar#}' +#try 'foo ${^}' #try 'foo `bar`' #try 'foo &&' #try '{ foo; }' @@ -649,3 +649,7 @@ try 'foo ${^}' #try 'foo $(bar) baz' #try 'foo$(bar$(baz))qux' #try 'foo $((1 + 1))' +try '$((1 + 1))' +try '$((1 + (1 + 1)))' +try '$((1 + $(foo) + 1))' +try '$((1' |