summaryrefslogtreecommitdiffstats
path: root/parsing
diff options
context:
space:
mode:
Diffstat (limited to 'parsing')
-rw-r--r--parsing/lexer.sh238
-rw-r--r--parsing/parse.sh22
2 files changed, 137 insertions, 123 deletions
diff --git a/parsing/lexer.sh b/parsing/lexer.sh
index ad076dc..5c3f6c5 100644
--- a/parsing/lexer.sh
+++ b/parsing/lexer.sh
@@ -1,7 +1,9 @@
fname=
lineno=
+ln_off=
start=
c=
+wordexp=
tok=
tokens=
@@ -327,9 +329,6 @@ scan_word()
scan_wordexp()
{
- local wordexp=
- local ln_off=
- local mod=
local res=
local param=
local word=
@@ -340,115 +339,7 @@ scan_wordexp()
case "${c}" in
'{')
# Parameter expansion brace
- mod=true
- lgetc
- case "${c}" in
- '#')
- lgetc
- case "${c}" in
- [@*#?$!A-Za-z0-9_-])
- # String length
- # expansion
- if ! res="$(scan_param)"
- then
- exit 1
- fi
- ln_off=${res%%${RS}*}
- res="${res#*${RS}}"
- c="${res%%${RS}*}"
- res="${res#*${RS}}"
- param="${res%%${RS}*}"
- lineno=$((${lineno} + \
- ${ln_off}))
- # Disable modifications.
- mod=false
- ;;
- *)
- # Special parameter "#"
- param='#'
- ;;
- esac
- ;;
- *)
- if ! res="$(scan_param)"; then
- exit 1
- fi
- ln_off=${res%%${RS}*}
- res="${res#*${RS}}"
- c="${res%%${RS}*}"
- res="${res#*${RS}}"
- param="${res%%${RS}*}"
- lineno=$((${lineno} + ${ln_off}))
- ;;
- esac
- wordexp="\${${param}"
- if ${mod}; then
- # Check for modifications
- mod=false
- case "${c}" in
- ':')
- mod=true
- wordexp="${wordexp}${c}"
- lgetc
- case "${c}" in '-'|'='|'?'|'+')
- wordexp="${wordexp}${c}"
- lgetc
- ;;
- esac
- ;;
- '-'|'='|'?'|'+')
- mod=true
- wordexp="${wordexp}${c}"
- lgetc
- ;;
- '%')
- mod=true
- wordexp="${wordexp}${c}"
- lgetc
- case "${c}" in '%')
- wordexp="${wordexp}${c}"
- lgetc
- ;;
- esac
- ;;
- '#')
- mod=true
- wordexp="${wordexp}${c}"
- lgetc
- case "${c}" in '#')
- wordexp="${wordexp}${c}"
- lgetc
- ;;
- esac
- ;;
- esac
- fi
- if ${mod}; then
- # Get word.
- if ! res="$(scan_word true)"; then
- exit 1
- fi
- ln_off=${res%%${RS}*}
- res="${res#*${RS}}"
- c="${res%%${RS}*}"
- res="${res#*${RS}}"
- word="${res%%${RS}*}"
- # We must advance lineno because scan_word() was
- # run in a subshell.
- lineno=$((${lineno} + ${ln_off}))
- wordexp="${wordexp}${word}"
- dbg "param mod word: '$word'"
- fi
- # Check for right brace.
- case "${c}" in
- '}')
- wordexp="${wordexp}${c}"
- lgetc
- ;;
- *)
- synerr 'Missing "}"'
- ;;
- esac
+ scan_wordexp_param_brace
;;
'(')
# Arithmetic expansion or command substitution
@@ -496,6 +387,129 @@ scan_wordexp()
return 0
}
+scan_wordexp_param_brace()
+{
+ local mod=
+ local res=
+ local param=
+
+ ln_off=0
+ mod=true
+
+ lgetc
+ case "${c}" in
+ '#')
+ lgetc
+ case "${c}" in
+ [@*#?$!A-Za-z0-9_-])
+ # String length expansion
+ if ! res="$(scan_param)"; then
+ exit 1
+ fi
+ ln_off=${res%%${RS}*}
+ res="${res#*${RS}}"
+ c="${res%%${RS}*}"
+ res="${res#*${RS}}"
+ param="${res%%${RS}*}"
+ lineno=$((${lineno} + ${ln_off}))
+ # Disable modifications.
+ mod=false
+ ;;
+ *)
+ # Special parameter "#"
+ param='#'
+ ;;
+ esac
+ ;;
+ *)
+ if ! res="$(scan_param)"; then
+ exit 1
+ fi
+ ln_off=${res%%${RS}*}
+ res="${res#*${RS}}"
+ c="${res%%${RS}*}"
+ res="${res#*${RS}}"
+ param="${res%%${RS}*}"
+ lineno=$((${lineno} + ${ln_off}))
+ ;;
+ esac
+ wordexp="\${${param}"
+
+ # If modifications are allowed
+ if ${mod}; then
+ # Check for modifications.
+ mod=false
+ case "${c}" in
+ ':')
+ mod=true
+ wordexp="${wordexp}${c}"
+ lgetc
+ case "${c}" in '-'|'='|'?'|'+')
+ wordexp="${wordexp}${c}"
+ lgetc
+ ;;
+ esac
+ ;;
+ '-'|'='|'?'|'+')
+ mod=true
+ wordexp="${wordexp}${c}"
+ lgetc
+ ;;
+ '%')
+ mod=true
+ wordexp="${wordexp}${c}"
+ lgetc
+ case "${c}" in '%')
+ wordexp="${wordexp}${c}"
+ lgetc
+ ;;
+ esac
+ ;;
+ '#')
+ mod=true
+ wordexp="${wordexp}${c}"
+ lgetc
+ case "${c}" in '#')
+ wordexp="${wordexp}${c}"
+ lgetc
+ ;;
+ esac
+ ;;
+ esac
+ fi
+
+ # If a modification was found
+ if ${mod}; then
+ # Get word.
+ if ! res="$(scan_word true)"; then
+ exit 1
+ fi
+ ln_off=${res%%${RS}*}
+ res="${res#*${RS}}"
+ c="${res%%${RS}*}"
+ res="${res#*${RS}}"
+ word="${res%%${RS}*}"
+ # We must advance lineno because scan_word() was run in a
+ # subshell.
+ lineno=$((${lineno} + ${ln_off}))
+ wordexp="${wordexp}${word}"
+ dbg "param mod word: '$word'"
+ fi
+
+ # Check for right brace.
+ case "${c}" in
+ '}')
+ wordexp="${wordexp}${c}"
+ lgetc
+ ;;
+ *)
+ synerr 'Missing "}"'
+ ;;
+ esac
+
+ return 0
+}
+
scan_param()
{
local param=
diff --git a/parsing/parse.sh b/parsing/parse.sh
index a71f90b..8f73b32 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; }'
@@ -643,9 +643,9 @@ try()
#try 'foo(){ bar; }'
#try 'case foo in bar) baz;; (qux) quux;; quux);; esac'
#try 'foo bar ( baz )'
-try 'foo $(bar)'
-try 'foo $(bar); baz'
-try 'foo $(bar)' 'baz'
-try 'foo $(bar) baz'
-try 'foo$(bar$(baz))qux'
+#try 'foo $(bar)'
+#try 'foo $(bar); baz'
+#try 'foo $(bar)' 'baz'
+#try 'foo $(bar) baz'
+#try 'foo$(bar$(baz))qux'
#try 'foo $((1 + 1))'