summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorP. 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)
commit9e2a93ddddeb89aa2512f2c6ee09a740729d9704 (patch)
treee5f31dcad1d7e50506632dc715951729a049acd9
parent292939d65a7ee4ceff225cb9bea671afc837f3b4 (diff)
downloadeggshell-9e2a93ddddeb89aa2512f2c6ee09a740729d9704.zip
eggshell-9e2a93ddddeb89aa2512f2c6ee09a740729d9704.tar.gz
eggshell-9e2a93ddddeb89aa2512f2c6ee09a740729d9704.tar.bz2
Implement arithmetic expansion
-rw-r--r--parsing/lexer.sh61
-rw-r--r--parsing/parse.sh16
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'