summaryrefslogtreecommitdiffstats
path: root/parsing
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2016-02-20 12:23:16 (EST)
committer P. J. McDermott <pj@pehjota.net>2016-02-20 12:23:16 (EST)
commitac6cc6b2405bb6d3775344a873fb1172f38f1c7e (patch)
tree8dd9d72f3a5fc3095418bdeb57c8b550f2784704 /parsing
parente221064cecfad291e65609e7412f074a64a6f5e4 (diff)
downloadeggshell-ac6cc6b2405bb6d3775344a873fb1172f38f1c7e.zip
eggshell-ac6cc6b2405bb6d3775344a873fb1172f38f1c7e.tar.gz
eggshell-ac6cc6b2405bb6d3775344a873fb1172f38f1c7e.tar.bz2
Implement command substitution (warning: ugly and broken)
Diffstat (limited to 'parsing')
-rw-r--r--parsing/lexer.sh51
-rw-r--r--parsing/parse.sh22
2 files changed, 63 insertions, 10 deletions
diff --git a/parsing/lexer.sh b/parsing/lexer.sh
index b03878d..1e9b2e0 100644
--- a/parsing/lexer.sh
+++ b/parsing/lexer.sh
@@ -276,6 +276,7 @@ scan_wordexp()
local res=
local param=
local word=
+ local toks=
wordexp=''
ln_off=0
@@ -398,8 +399,30 @@ scan_wordexp()
;;
*)
# Command substitution
- synerr 'Command substitution is %s' \
- 'not yet supported'
+ if ! res="$(parse_sub "${fname}" \
+ ${lineno} "${c}" false)"
+ then
+ exit 1
+ fi
+ ln_off=${res%%${RS}*}
+ res="${res#*${RS}}"
+ c="${res%%${RS}*}"
+ res="${res#*${RS}}"
+ toks="${res%%${RS}*}"
+ lineno=${ln_off}
+ wordexp="\$(${STX}${toks}${ETX}"
+ # Get ")"
+ case "${c}" in
+ ')')
+ wordexp="${wordexp}${c}"
+ pgetc
+ ;;
+ *)
+ echo "c: '$c'" >&2
+ echo "wordexp: $wordexp" >&2
+ synerr 'Missing ")"'
+ ;;
+ esac
;;
esac
;;
@@ -600,15 +623,35 @@ init_lexer()
{
local fn="${1}"
local ln="${2}"
- shift 2
+ local char="${3}"
+ shift 3
fname="${fn}"
lineno=${ln}
tokens=''
- pgetc
+ case "${char}" in
+ '')
+ pgetc
+ ;;
+ *)
+ c="${char}"
+ ;;
+ esac
next
}
+get_lineno()
+{
+ printf '%d' ${lineno}
+ return 0
+}
+
+get_lexer_char()
+{
+ printf '%c' "${c}"
+ return 0
+}
+
get_tokens()
{
printf '%s' "${tokens}"
diff --git a/parsing/parse.sh b/parsing/parse.sh
index a28aad2..4d4b9ea 100644
--- a/parsing/parse.sh
+++ b/parsing/parse.sh
@@ -583,20 +583,28 @@ sequential_sep()
return 1
}
+# Maybe parse() should just tell the lexer what the starting production (parser
+# entry point) is.
parse_sub()
{
local fn="${1}"
local ln="${2}"
- shift 2
+ local lexer_char="${3}"
+ local complete="${4}"
+ shift 3
- init_lexer "${fn}" ${ln}
+ init_lexer "${fn}" ${ln} "${lexer_char}"
# If this returns (does not exit), there are no errors.
complete_command
- if ! accept T_EOF; then
+ if ${complete} && ! accept T_EOF; then
synexp ''
fi
+ get_lineno
+ printf '%c' "${RS}"
+ get_lexer_char
+ printf '%c' "${RS}"
get_tokens
return 0
@@ -606,8 +614,10 @@ parse()
{
local fn="${1}"
shift 1
+ local toks=
- if parse_sub "${fn}" 1; then
+ if toks="$(parse_sub "${fn}" 1 '' true)"; then
+ printf '%s\n' "${toks#*${RS}*${RS}}"
return 0
fi
return 1
@@ -640,7 +650,7 @@ try()
}
#try '"foo bar" && $baz || qux' '${quux%uux quuux'
-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}'
@@ -659,5 +669,5 @@ try '"foo bar" && $baz || qux' '${quux%uux } quuux'
#try 'foo(){ bar; }'
#try 'case foo in bar) baz;; (qux) quux;; quux);; esac'
#try 'foo bar ( baz )'
-#try 'foo $(bar)'
+try 'foo $(bar)'
#try 'foo $((1 + 1))'