feat(package): hemar: interpolation
This commit is contained in:
@@ -201,10 +201,10 @@ json_escape() {
|
|||||||
# finds close pattern and store the char to the stage buffers separating by spaces
|
# finds close pattern and store the char to the stage buffers separating by spaces
|
||||||
parse_tag() {
|
parse_tag() {
|
||||||
local char="${1:?}"
|
local char="${1:?}"
|
||||||
# NOTE: any return 1 - skip char, regular_char + return 1 - write char
|
# NOTE: any return 1 - skip char, regular_char + return 1 - write char
|
||||||
# TAG_seen_first_ws - we've already handled the first whitespace after `{[...]`
|
# TAG_seen_first_ws - we've already handled the first whitespace after `{[...]`
|
||||||
# TAG_in_ws_run - we’re currently in a run of whitespace chars
|
# TAG_in_ws_run - we’re currently in a run of whitespace chars
|
||||||
# TAG_pending_close - we saw `]` and are checking if the next char is `}`
|
# TAG_pending_close - we saw `]` and are checking if the next char is `}`
|
||||||
|
|
||||||
string_grammar() {
|
string_grammar() {
|
||||||
if [ "${TAG_in_quoted_string+x}" ]; then
|
if [ "${TAG_in_quoted_string+x}" ]; then
|
||||||
@@ -215,7 +215,7 @@ parse_tag() {
|
|||||||
;;
|
;;
|
||||||
'.')
|
'.')
|
||||||
TAG_dote=1
|
TAG_dote=1
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
*) log error "unexpected end of quote on $WHITE$LINE_N$NC:$WHITE$CHAR_N" ;;
|
*) log error "unexpected end of quote on $WHITE$LINE_N$NC:$WHITE$CHAR_N" ;;
|
||||||
esac
|
esac
|
||||||
@@ -227,13 +227,14 @@ parse_tag() {
|
|||||||
|
|
||||||
# shellcheck disable=SC1003
|
# shellcheck disable=SC1003
|
||||||
case "$char" in
|
case "$char" in
|
||||||
'['|']'|'{'|'}'|'"'|'\')
|
']'|'}'|'"'|'\')
|
||||||
log error "not allowed character $WHITE$char$NC on $WHITE$LINE_N$NC:$WHITE$CHAR_N"
|
log error "not allowed character $WHITE$char$NC on $WHITE$LINE_N$NC:$WHITE$CHAR_N"
|
||||||
log error "try to use quoted string"
|
log error "try to use quoted string"
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
'.')
|
'.')
|
||||||
TAG_dote=1
|
TAG_dote=1
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
@@ -247,11 +248,12 @@ parse_tag() {
|
|||||||
[ ${TAG_in_ws_run+x} ] && {
|
[ ${TAG_in_ws_run+x} ] && {
|
||||||
unset TAG_in_ws_run
|
unset TAG_in_ws_run
|
||||||
if [ "${TAG_seen_first_ws+x}" ]; then
|
if [ "${TAG_seen_first_ws+x}" ]; then
|
||||||
|
log trace "tag in ws -> type: \`${TAG_type:-}\`"
|
||||||
case "${TAG_type:-unknown}" in
|
case "${TAG_type:-unknown}" in
|
||||||
unknown) finalize_first_arg ;;
|
unknown) finalize_first_arg ;;
|
||||||
for)
|
for)
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# grammar: for i in key."subkey" ; so we know
|
# grammar: for i in key."subkey" ; so we know
|
||||||
# 1st argument after `for` - string (name of variable)
|
# 1st argument after `for` - string (name of variable)
|
||||||
# 2nd - 'in' (just keyword)
|
# 2nd - 'in' (just keyword)
|
||||||
# 3rd - path (path to array in Model)
|
# 3rd - path (path to array in Model)
|
||||||
@@ -276,21 +278,25 @@ parse_tag() {
|
|||||||
printf '%s' "$1" >> "$CURRENT_STAGE_BUFFER"
|
printf '%s' "$1" >> "$CURRENT_STAGE_BUFFER"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ ! "${TAG_pending_close+x}" ] && [ "$char" = ']' ]; then
|
if ! [ "${TAG_in_quoted_string+x}" ]; then
|
||||||
TAG_pending_close=1
|
if [ ! "${TAG_pending_close+x}" ] && [ "$char" = ']' ]; then
|
||||||
# NOTE: skip ']' but remember to check next char for a possible '}'
|
TAG_pending_close=1
|
||||||
return 1
|
# NOTE: skip ']' but remember to check next char for a possible '}'
|
||||||
elif [ "${TAG_pending_close+x}" ]; then
|
return 1
|
||||||
unset TAG_pending_close
|
elif [ "${TAG_pending_close+x}" ]; then
|
||||||
if [ "$char" = '}' ]; then
|
unset TAG_pending_close
|
||||||
# NOTE: found `]}` — finish bracket parsing
|
if [ "$char" = '}' ]; then
|
||||||
return 0
|
finish
|
||||||
|
|
||||||
|
# NOTE: found `]}` — finish bracket parsing
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
# NOTE: `]` was not followed by `}`, so emit the `]` we skipped
|
||||||
|
printf ']' >> "$CURRENT_STAGE_BUFFER"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# NOTE: `]` was not followed by `}`, so emit the `]` we skipped
|
is_ws "$char" && { TAG_in_ws_run=1; return 1; }
|
||||||
printf ']' >> "$CURRENT_STAGE_BUFFER"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
is_ws "$char" && { TAG_in_ws_run=1; return 1; }
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "${TAG_grammar_mode:-unknown}" in
|
case "${TAG_grammar_mode:-unknown}" in
|
||||||
@@ -309,12 +315,12 @@ parse_tag() {
|
|||||||
|
|
||||||
string_grammar || return 1
|
string_grammar || return 1
|
||||||
if [ ${TAG_dote+x} ]; then
|
if [ ${TAG_dote+x} ]; then
|
||||||
TAG_grammar_mode=path
|
TAG_grammar_mode=path
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
path)
|
path)
|
||||||
if [ "${TAG_dote+x}" ]; then
|
if [ "${TAG_dote+x}" ]; then
|
||||||
log notice "suka"
|
log notice "suka"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${TAG_in_ws_run+x}" ] && [ "$char" = '"' ] || [ "${TAG_dote+x}" ] && [ "$char" = '"' ]; then
|
if [ "${TAG_in_ws_run+x}" ] && [ "$char" = '"' ] || [ "${TAG_dote+x}" ] && [ "$char" = '"' ]; then
|
||||||
@@ -325,7 +331,7 @@ parse_tag() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
[ "${TAG_dote+x}" ] && unset TAG_dote
|
[ "${TAG_dote+x}" ] && unset TAG_dote
|
||||||
|
|
||||||
|
|
||||||
string_grammar || return 1
|
string_grammar || return 1
|
||||||
;;
|
;;
|
||||||
@@ -350,7 +356,25 @@ parse_tag() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finish() {
|
||||||
|
case "${TAG_type:-unknown}" in
|
||||||
|
unknown)
|
||||||
|
finish_interpolation_tag
|
||||||
|
;;
|
||||||
|
done)
|
||||||
|
finish_done_tag
|
||||||
|
;;
|
||||||
|
'{[')
|
||||||
|
finish_bracket_tag
|
||||||
|
;;
|
||||||
|
for) ;;
|
||||||
|
*) log panic 'unexpected TAG_type on finish'; exit 13; ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
finalize_first_arg() {
|
finalize_first_arg() {
|
||||||
|
log trace "finalize first arg"
|
||||||
|
log trace "buffer: $(cat "$CURRENT_STAGE_BUFFER")"
|
||||||
case "$(cat "$CURRENT_STAGE_BUFFER")" in
|
case "$(cat "$CURRENT_STAGE_BUFFER")" in
|
||||||
for)
|
for)
|
||||||
TAG_type='for'
|
TAG_type='for'
|
||||||
@@ -360,34 +384,47 @@ finalize_first_arg() {
|
|||||||
exit 13
|
exit 13
|
||||||
;;
|
;;
|
||||||
done)
|
done)
|
||||||
TAG_type='done'
|
finish_done_tag
|
||||||
TAG_next_argument_redgect=1
|
|
||||||
# NOTE: Do not save {[ done ]} to the AST becouse it is useless there
|
|
||||||
;;
|
;;
|
||||||
'{[')
|
'{[')
|
||||||
TAG_type='actual bracket'
|
finish_bracket_tag
|
||||||
TAG_next_argument_redgect=1
|
|
||||||
if yq -e "${AST_key}[-1].type == \"text\"" "$AST" > /dev/null; then
|
|
||||||
yq -o j -i "${AST_key}[-1].value += \"{[\"" "$AST"
|
|
||||||
else
|
|
||||||
yq -o j -i "$AST_key += [{
|
|
||||||
\"type\": \"text\",
|
|
||||||
\"value\": \"{[\"
|
|
||||||
}]" "$AST"
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
*) # interpolation tag
|
*) # interpolation tag
|
||||||
TAG_type='interpolation'
|
finish_interpolation_tag
|
||||||
TAG_next_argument_redgect=1
|
|
||||||
buf=$(cat "$STAGE_BUFFER_1")
|
|
||||||
yq -o j -i "$AST_key += [{
|
|
||||||
\"type\": \"interpolation\",
|
|
||||||
\"path\": \"$(json_escape "$buf")\"
|
|
||||||
}]" "$AST"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finish_done_tag() {
|
||||||
|
TAG_type='done'
|
||||||
|
TAG_next_argument_redgect=1
|
||||||
|
# NOTE: Do not save {[ done ]} to the AST becouse it is useless there
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_bracket_tag() {
|
||||||
|
TAG_type='actual bracket'
|
||||||
|
TAG_next_argument_redgect=1
|
||||||
|
if yq -e "${AST_key}[-1].type == \"text\"" "$AST" > /dev/null; then
|
||||||
|
yq -o j -i "${AST_key}[-1].value += \"{[\"" "$AST"
|
||||||
|
else
|
||||||
|
yq -o j -i "$AST_key += [{
|
||||||
|
\"type\": \"text\",
|
||||||
|
\"value\": \"{[\"
|
||||||
|
}]" "$AST"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_interpolation_tag() {
|
||||||
|
log trace 'finish interpolation tag'
|
||||||
|
TAG_type='interpolation'
|
||||||
|
TAG_next_argument_redgect=1
|
||||||
|
buf=$(cat "$STAGE_BUFFER_1")
|
||||||
|
yq -o j -i "$AST_key += [{
|
||||||
|
\"type\": \"interpolation\",
|
||||||
|
\"path\": \"$(json_escape "$buf")\"
|
||||||
|
}]" "$AST"
|
||||||
|
}
|
||||||
|
|
||||||
# finds open pattern and stores the char to the STAGE_BUFFER_1
|
# finds open pattern and stores the char to the STAGE_BUFFER_1
|
||||||
find_open_pattern() {
|
find_open_pattern() {
|
||||||
local char="${1:?}"
|
local char="${1:?}"
|
||||||
@@ -414,7 +451,7 @@ parse() {
|
|||||||
# Text Stage - save char in STAGE_BUFFER_1 until next tag opens
|
# Text Stage - save char in STAGE_BUFFER_1 until next tag opens
|
||||||
0)
|
0)
|
||||||
if find_open_pattern "$char"; then
|
if find_open_pattern "$char"; then
|
||||||
log debug "open pattern founded"
|
log trace "open pattern founded"
|
||||||
buf=$(cat "$CURRENT_STAGE_BUFFER")
|
buf=$(cat "$CURRENT_STAGE_BUFFER")
|
||||||
yq -o j -i "$AST_key += [{
|
yq -o j -i "$AST_key += [{
|
||||||
\"type\": \"text\",
|
\"type\": \"text\",
|
||||||
@@ -430,9 +467,10 @@ parse() {
|
|||||||
log_buffers
|
log_buffers
|
||||||
|
|
||||||
# zero-initialization
|
# zero-initialization
|
||||||
|
unset TAG_seen_first_ws TAG_in_ws_run TAG_pending_close TAG_type TAG_next_argument_redgect TAG_grammar_mode TAG_in_quoted_string TAG_dote
|
||||||
|
|
||||||
buf_reset
|
buf_reset
|
||||||
STAGE=1
|
STAGE=0
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
@@ -470,12 +508,16 @@ done
|
|||||||
|
|
||||||
CHAR_N=1
|
CHAR_N=1
|
||||||
LINE_N=1
|
LINE_N=1
|
||||||
#LINE_NUMBER=1
|
|
||||||
while :; do
|
while :; do
|
||||||
# read exactly 1 byte; preserve newlines
|
hex="$(dd bs=1 count=1 2>/dev/null | od -An -t u1)"
|
||||||
if ! char="$(dd bs=1 count=1 2>/dev/null)"; then
|
|
||||||
break
|
[ -z "$hex" ] && {
|
||||||
fi
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
char="$(printf "\\$(printf '%03o' "$hex")")"
|
||||||
|
|
||||||
# NOTE: if $char is empty, it because `dd` returned '\n' but `$(...)`
|
# NOTE: if $char is empty, it because `dd` returned '\n' but `$(...)`
|
||||||
# removed it as trailing '\n', so I set $char as '\n' here
|
# removed it as trailing '\n', so I set $char as '\n' here
|
||||||
@@ -485,11 +527,15 @@ while :; do
|
|||||||
'
|
'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log trace "char: $WHITE$char"
|
||||||
|
|
||||||
parse "${char:?}"
|
parse "${char:?}"
|
||||||
|
|
||||||
CHAR_N=$((CHAR_N+1))
|
CHAR_N=$((CHAR_N+1))
|
||||||
done
|
done
|
||||||
|
|
||||||
|
log debug 'finishing'
|
||||||
|
|
||||||
# finish TEXT tag if file ends on it
|
# finish TEXT tag if file ends on it
|
||||||
if [ "$STAGE" -eq 0 ]; then
|
if [ "$STAGE" -eq 0 ]; then
|
||||||
if [ "${open_tag_flag+x}" ]; then
|
if [ "${open_tag_flag+x}" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user