aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bashast/libbashWalker.g29
-rw-r--r--scripts/var_def.bash8
-rw-r--r--src/core/interpreter.h9
-rw-r--r--src/core/symbols.hpp5
-rw-r--r--src/core/tests/interpreter_test.cpp9
5 files changed, 53 insertions, 7 deletions
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 5e3fd6e..5d5b557 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -217,19 +217,34 @@ var_def[bool local]
else
walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index);
}
- |^(EQUALS libbash_name=name_base ^(ARRAY (
- (expr=string_expr
- |^(EQUALS value=arithmetics {
- set_index(libbash_name, index, value);
- } expr=string_expr))
- { values[index++] = expr.libbash_value; })*
- )){
+ |^(EQUALS libbash_name=name_base array_def_helper[libbash_name, values, index]){
if(local)
walker->define_local(libbash_name, values);
else
walker->define(libbash_name, values);
+ }
+ |^(PLUS_ASSIGN libbash_name=name_base {
+ index = walker->get_max_index(libbash_name) + 1;
+ if(index == 1) // The variable is not defined
+ index = 0;
+ } array_def_helper[libbash_name, values, index]){
+ if(local)
+ throw libbash::unsupported_exception("Appending array to local variable is not supported");
+ for(auto iter = values.begin(); iter != values.end(); ++iter)
+ walker->set_value(libbash_name, iter->second, iter->first);
};
+array_def_helper[const std::string& libbash_name, std::map<unsigned, std::string>& values, unsigned index]
+ :^(ARRAY (
+ (
+ expr=string_expr
+ |^(EQUALS value=arithmetics {
+ set_index(libbash_name, index, value);
+ } expr=string_expr)
+ )
+ { values[index++] = expr.libbash_value; }
+ )*);
+
string_expr returns[std::string libbash_value, bool quoted]
@init {
$quoted = true;
diff --git a/scripts/var_def.bash b/scripts/var_def.bash
index e757b16..96747c0 100644
--- a/scripts/var_def.bash
+++ b/scripts/var_def.bash
@@ -88,3 +88,11 @@ function foo() {
foo
bar=@
echo $bar
+ARRAY11=(1 2 3 [10]=15)
+ARRAY11+=(1 [15]=20)
+echo ${ARRAY11[@]}
+ARRAY12+=(4 5 6)
+echo ${ARRAY12[@]}
+ARRAY13=()
+ARRAY13+=(4 5 6)
+echo ${ARRAY13[@]}
diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index fcc3294..fbb9d48 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -461,6 +461,15 @@ public:
/// \return the length of the array
variable::size_type get_array_length(const std::string& name) const;
+ /// \brief get the max index of an array
+ /// \param name the name of the array
+ /// \return the max index of the array
+ variable::size_type get_max_index(const std::string& name) const
+ {
+ auto var = resolve_variable(name);
+ return var ? var->get_max_index() : 0;
+ }
+
/// \brief get all array elements concatenated by space
/// \param name the name of the array
/// \param[out] result the concatenated string
diff --git a/src/core/symbols.hpp b/src/core/symbols.hpp
index 8dd8cd3..e9cb019 100644
--- a/src/core/symbols.hpp
+++ b/src/core/symbols.hpp
@@ -215,6 +215,11 @@ public:
return value.size();
}
+ size_type get_max_index() const
+ {
+ return value.size() == 0 ? 0 : value.rbegin()->first;
+ }
+
/// \brief check whether the value of the variable is null
/// \return whether the value of the variable is null
bool is_unset(const unsigned index=0) const
diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpreter_test.cpp
index ecbcfd9..c3278d0 100644
--- a/src/core/tests/interpreter_test.cpp
+++ b/src/core/tests/interpreter_test.cpp
@@ -146,6 +146,15 @@ TEST(interpreter, get_array_values)
EXPECT_FALSE(walker.resolve_array("undefined", array_values));
}
+TEST(interpreter, get_max_index)
+{
+ interpreter walker;
+ std::map<unsigned, std::string> values = {{0, "1"}, {1, "2"}, {5, "3"}};
+ walker.define("array", values);
+
+ EXPECT_EQ(5, walker.get_max_index("array"));
+}
+
TEST(interpreter, unset_arrays)
{
interpreter walker;