summaryrefslogtreecommitdiffstats
path: root/parsing/parse.sh
diff options
context:
space:
mode:
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