summaryrefslogtreecommitdiffstats
path: root/parsing/parse.sh
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2016-02-19 04:01:32 (EST)
committer P. J. McDermott <pj@pehjota.net>2016-02-19 04:01:32 (EST)
commitf6e55a026abf33867141896b1e227e791942c2a3 (patch)
treebe82488bad31428eaf3a98583bbf56aaa0610804 /parsing/parse.sh
parenta9f84d9757aad50db3f1d7e11c6e779b920ed96b (diff)
downloadeggshell-f6e55a026abf33867141896b1e227e791942c2a3.zip
eggshell-f6e55a026abf33867141896b1e227e791942c2a3.tar.gz
eggshell-f6e55a026abf33867141896b1e227e791942c2a3.tar.bz2
[WIP] Add lexer/parser demo
Diffstat (limited to 'parsing/parse.sh')
-rw-r--r--parsing/parse.sh133
1 files changed, 133 insertions, 0 deletions
diff --git a/parsing/parse.sh b/parsing/parse.sh
new file mode 100644
index 0000000..2ac4215
--- /dev/null
+++ b/parsing/parse.sh
@@ -0,0 +1,133 @@
+HT="$(printf '\t.')"; HT="${HT%.}"
+LF="$(printf '\n.')"; LF="${LF%.}"
+RS="$(printf '\036.')"; RS="${RS%.}"
+US="$(printf '\037.')"; US="${US%.}"
+
+. ./tokens.sh
+. ./lexer.sh
+
+complete_command()
+{
+ if list; then
+ separator
+ return 0
+ fi
+ return 1
+}
+
+list()
+{
+ if and_or; then
+ while separator_op; do
+ if ! and_or; then
+ return 1
+ fi
+ done
+ return 0
+ fi
+ return 1
+}
+and_or()
+{
+ if pipeline; then
+ while accept T_AND_IF || accept T_OR_IF; do
+ if ! linebreak || ! pipeline; then
+ return 1
+ fi
+ done
+ return 0
+ fi
+ return 1
+}
+pipeline()
+{
+ accept T_BANG
+ if pipe_sequence; then
+ return 0
+ fi
+ return 1
+}
+
+pipe_sequence()
+{
+ if command; then
+ while accept T_PIPE; do
+ if ! linebreak || ! command; then
+ return 1
+ fi
+ done
+ return 0
+ fi
+ return 1
+}
+
+command()
+{
+ # XXX: Unfinished
+ accept T_WORD
+}
+
+
+
+newline_list()
+{
+ if accept T_NEWLINE; then
+ while accept T_NEWLINE; do
+ :
+ done
+ return 0
+ fi
+ return 1
+}
+linebreak()
+{
+ newline_list
+ return 0
+}
+
+separator_op()
+{
+ if accept T_AND || accept T_SEMI; then
+ return 0
+ fi
+ return 1
+}
+
+separator()
+{
+ if separator_op && linebreak; then
+ return 0
+ elif newline_list; then
+ return 0
+ fi
+ return 1
+}
+
+parse()
+{
+ local fn="${1}"
+ shift 1
+
+ init_lexer "${fn}"
+ while complete_command; do :; done
+ if :; then # TODO: Test for EOF or errors
+ get_tokens
+ return 0
+ fi
+ return 1
+}
+
+if tokens="$(printf '%s\n' '"foo bar" && $baz || qux' '${quux%uux } quuux' | \
+ parse -)"; then
+ IFS="${RS}"
+ for t in ${tokens}; do
+ printf 'Token: %s\n' "$(tokname "${t}")"
+ case "${t%${US}*}" in T_WORD)
+ printf ' "%s"\n' "${t#T_WORD${US}}"
+ ;;
+ esac
+ done
+ unset IFS
+else
+ echo FAIL
+fi