public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-14  4:50 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-14  4:50 UTC (permalink / raw
  To: gentoo-commits

commit:     e69a687ae1d3db7c61179b8492ee51e47dc0569a
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Tue Apr 12 11:11:32 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Thu Apr 14 01:33:29 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=e69a687a

Implement array element in arithmetic expansion

Array element reference and assignment in arithmetic expansion are
supported now.

---
 bashast/libbashWalker.g                     |   72 ++++++++++++++++----------
 scripts/arithmetic_assignment.ebuild        |    2 +
 scripts/arithmetic_assignment.ebuild.result |    3 +
 scripts/binary_arithmetic.ebuild            |   28 ++++++++++-
 scripts/binary_arithmetic.ebuild.result     |   26 +++++++++-
 src/core/interpreter.h                      |   22 ++++----
 6 files changed, 112 insertions(+), 41 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 47634e8..05c1127 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -178,6 +178,22 @@ var_ref [bool double_quoted] returns[std::string libbash_value]:
 	}
 	|^(VAR_REF libbash_string=var_expansion) { $libbash_value = libbash_string; };
 
+// Only used in arithmetic expansion
+primary returns[std::string libbash_value, unsigned index]:
+	(^(VAR_REF name)) => ^(VAR_REF name) {
+		$libbash_value = $name.libbash_value;
+		$index = $name.index;
+	}
+	|name {
+		$libbash_value = $name.libbash_value;
+		$index = $name.index;
+	}
+	// array[@] and array[*] is meaningless to arithmetic expansion so true/false are both ok.
+	|^(VAR_REF libbash_string=var_ref[false]) {
+		$libbash_value = libbash_string;
+		$index = 0;
+	};
+
 // shell arithmetic
 arithmetics returns[int value]
 :
@@ -205,45 +221,45 @@ arithmetics returns[int value]
 	|^(ARITHMETIC_CONDITION cnd=arithmetics l=arithmetics r=arithmetics){
 		$value = walker->arithmetic_condition(cnd, l, r);
 	}
-	|^(VAR_REF name) {
-		$value = walker->resolve<int>($name.libbash_value);
+	|primary {
+		$value = walker->resolve<int>($primary.libbash_value, $primary.index);
 	}
-	|^(PRE_INCR ^(VAR_REF name)){ $value = walker->pre_incr($name.libbash_value); }
-	|^(PRE_DECR ^(VAR_REF name)){ $value = walker->pre_decr($name.libbash_value); }
-	|^(POST_INCR ^(VAR_REF name)){ $value = walker->post_incr($name.libbash_value); }
-	|^(POST_DECR ^(VAR_REF name)){ $value = walker->post_decr($name.libbash_value); }
-	|^(EQUALS name l=arithmetics) {
-		$value = walker->set_value($name.libbash_value, l);
+	|^(PRE_INCR primary){ $value = walker->pre_incr($primary.libbash_value, $primary.index); }
+	|^(PRE_DECR primary){ $value = walker->pre_decr($primary.libbash_value, $primary.index); }
+	|^(POST_INCR primary){ $value = walker->post_incr($primary.libbash_value, $primary.index); }
+	|^(POST_DECR primary){ $value = walker->post_decr($primary.libbash_value, $primary.index); }
+	|^(EQUALS primary l=arithmetics) {
+		$value = walker->set_value($primary.libbash_value, l, $primary.index);
 	}
-	|^(MUL_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::multiply, $name.libbash_value, l);
+	|^(MUL_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::multiply, $primary.libbash_value, l, $primary.index);
 	}
-	|^(DIVIDE_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::divide, $name.libbash_value, l);
+	|^(DIVIDE_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::divide, $primary.libbash_value, l, $primary.index);
 	}
-	|^(MOD_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::mod, $name.libbash_value, l);
+	|^(MOD_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::mod, $primary.libbash_value, l, $primary.index);
 	}
-	|^(PLUS_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::plus, $name.libbash_value, l);
+	|^(PLUS_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::plus, $primary.libbash_value, l, $primary.index);
 	}
-	|^(MINUS_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::minus, $name.libbash_value, l);
+	|^(MINUS_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::minus, $primary.libbash_value, l, $primary.index);
 	}
-	|^(LSHIFT_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::left_shift, $name.libbash_value, l);
+	|^(LSHIFT_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::left_shift, $primary.libbash_value, l, $primary.index);
 	}
-	|^(RSHIFT_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::right_shift, $name.libbash_value, l);
+	|^(RSHIFT_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::right_shift, $primary.libbash_value, l, $primary.index);
 	}
-	|^(AND_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::bitwiseand, $name.libbash_value, l);
+	|^(AND_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::bitwiseand, $primary.libbash_value, l, $primary.index);
 	}
-	|^(XOR_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::bitwisexor, $name.libbash_value, l);
+	|^(XOR_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::bitwisexor, $primary.libbash_value, l, $primary.index);
 	}
-	|^(OR_ASSIGN name l=arithmetics) {
-		$value = walker->assign(&interpreter::bitwiseor, $name.libbash_value, l);
+	|^(OR_ASSIGN primary l=arithmetics) {
+		$value = walker->assign(&interpreter::bitwiseor, $primary.libbash_value, l, $primary.index);
 	}
 	| NUMBER { $value = walker->parse_int($NUMBER);}
 	| DIGIT { $value = walker->parse_int($DIGIT);}

diff --git a/scripts/arithmetic_assignment.ebuild b/scripts/arithmetic_assignment.ebuild
index 20bcc44..27e2ee5 100644
--- a/scripts/arithmetic_assignment.ebuild
+++ b/scripts/arithmetic_assignment.ebuild
@@ -9,4 +9,6 @@ FOO007="$((value>>=2))"
 FOO008="$((value&=10))"
 FOO009="$((value^=5))"
 FOO010="$((value|=10))"
+FOO011=("CREATED" 2)
+FOO012="$((${FOO011[0]}=10))"
 value="$((100))"

diff --git a/scripts/arithmetic_assignment.ebuild.result b/scripts/arithmetic_assignment.ebuild.result
index 64863b5..9f47242 100644
--- a/scripts/arithmetic_assignment.ebuild.result
+++ b/scripts/arithmetic_assignment.ebuild.result
@@ -1,3 +1,4 @@
+CREATED=10
 FOO001=1000
 FOO002=100
 FOO003=1
@@ -8,4 +9,6 @@ FOO007=1
 FOO008=0
 FOO009=5
 FOO010=15
+FOO011=CREATED 2
+FOO012=10
 value=100

diff --git a/scripts/binary_arithmetic.ebuild b/scripts/binary_arithmetic.ebuild
index a674f5c..bdc3d94 100644
--- a/scripts/binary_arithmetic.ebuild
+++ b/scripts/binary_arithmetic.ebuild
@@ -1,3 +1,4 @@
+ARRAY=(1 2 3 4 5)
 FOO001="$((0 || -2))"
 FOO002="$((0 || 0))"
 FOO003="$((-1 && 10))"
@@ -36,4 +37,29 @@ FOO033="$((++value+value++))"
 FOO034="$((10*(2+5)<<3%2**5))"
 FOO035="$((10*value<<3%2**5))"
 FOO036="$(( (20&5|3||1*100-20&5*10)+~(2*5) ))"
-value="$((100))"
+FOO037="$((ARRAY[0]++))"
+FOO038="$((++ARRAY[0]))"
+FOO039="$((ARRAY[0]--))"
+FOO040="$((--ARRAY[0]))"
+FOO041="$((ARRAY[8]=9))"
+FOO042="$((ARRAY[8]*=10))"
+FOO043="$((ARRAY[8]/=10))"
+FOO044="$((ARRAY[8]%=2))"
+FOO045="$((ARRAY[8]+=8))"
+FOO046="$((ARRAY[8]-=0))"
+FOO047="$((ARRAY[8]<<=1))"
+FOO048="$((ARRAY[8]>>=1))"
+FOO049="$((ARRAY[8]&=5))"
+FOO050="$((ARRAY[8]|=10))"
+FOO051="$((ARRAY[8]^=3))"
+PARTIAL[8]=5
+FOO052="$((PARTIAL[8]*=1))"
+# The following 3 just expand to non-exist variables
+FOO053="$((${#ARRAY[@]}))"
+FOO054="$((${ARRAY[5]:-10}))"
+FOO055="$((${ARRAY:0}))"
+value=100
+FOO056="value"
+FOO057="$((${FOO056}++))"
+FOO058="$((${FOO056}+=10))"
+ARRAY=(1 2 3 4 5)

diff --git a/scripts/binary_arithmetic.ebuild.result b/scripts/binary_arithmetic.ebuild.result
index b258fd0..63cfa28 100644
--- a/scripts/binary_arithmetic.ebuild.result
+++ b/scripts/binary_arithmetic.ebuild.result
@@ -1,3 +1,4 @@
+ARRAY=1 2 3 4 5
 FOO001=1
 FOO002=0
 FOO003=1
@@ -34,4 +35,27 @@ FOO033=206
 FOO034=560
 FOO035=8320
 FOO036=-10
-value=100
+FOO037=1
+FOO038=3
+FOO039=3
+FOO040=1
+FOO041=9
+FOO042=90
+FOO043=9
+FOO044=1
+FOO045=9
+FOO046=9
+FOO047=18
+FOO048=9
+FOO049=1
+FOO050=11
+FOO051=8
+FOO052=5
+FOO053=0
+FOO054=0
+FOO055=0
+FOO056=value
+FOO057=100
+FOO058=111
+PARTIAL=5
+value=111

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 4d51d5b..5ac5027 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -321,9 +321,9 @@ public:
   /// \brief perform pre-increment
   /// \param the variable name
   /// \return the increased value
-  int pre_incr(const std::string& name)
+  int pre_incr(const std::string& name, const unsigned index)
   {
-    int value = resolve<int>(name);
+    int value = resolve<int>(name, index);
     set_value(name, ++value);
     return value;
   }
@@ -331,9 +331,9 @@ public:
   /// \brief perform pre-decrement
   /// \param the variable name
   /// \return the decreased value
-  int pre_decr(const std::string& name)
+  int pre_decr(const std::string& name, const unsigned index)
   {
-    int value = resolve<int>(name);
+    int value = resolve<int>(name, index);
     set_value(name, --value);
     return value;
   }
@@ -341,9 +341,9 @@ public:
   /// \brief perform post-increment
   /// \param the variable name
   /// \return the original value
-  int post_incr(const std::string& name)
+  int post_incr(const std::string& name, const unsigned index)
   {
-    int value = resolve<int>(name);
+    int value = resolve<int>(name, index);
     set_value(name, value + 1);
     return value;
   }
@@ -351,9 +351,9 @@ public:
   /// \brief perform post-decrement
   /// \param the variable name
   /// \return the original value
-  int post_decr(const std::string& name)
+  int post_decr(const std::string& name, const unsigned index)
   {
-    int value = resolve<int>(name);
+    int value = resolve<int>(name, index);
     set_value(name, value - 1);
     return value;
   }
@@ -363,10 +363,10 @@ public:
   /// \param the name of the variable
   /// \param the value to assign
   /// \return the new value of the variable
-  int assign(std::function<int(int,int)> f, const std::string& name, int value)
+  int assign(std::function<int(int,int)> f, const std::string& name, int value, const unsigned index)
   {
-    int new_value = f(resolve<int>(name), value);
-    set_value(name, new_value);
+    int new_value = f(resolve<int>(name, index), value);
+    set_value(name, new_value, index);
     return new_value;
   }
 



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2012-08-19 14:54 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2012-08-19 14:54 UTC (permalink / raw
  To: gentoo-commits

commit:     b2f509d72462bbf3dcd89d0164e435556980e3ba
Author:     André Aparício <aparicio99 <AT> gmail <DOT> com>
AuthorDate: Sat Jul 21 01:52:35 2012 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Sun Aug 19 14:52:07 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=b2f509d7

Walker: Support string operations on arrays

When a variable expansion applies some string operation like replace on
the whole array, apply the operation to every element in the array.

---
 bashast/libbashWalker.g    |   83 +++++++++++++++++++++++++------------------
 scripts/var_expansion.bash |   11 ++++++
 src/core/interpreter.cpp   |   10 +++++
 src/core/interpreter.h     |    9 ++++-
 4 files changed, 77 insertions(+), 36 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 460ed0c..768129f 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -188,6 +188,14 @@ options
 					walker->set_input_stream(_in);
 				}
 		};
+
+		std::string replace_expansion(const std::string name, int index, std::function<void(std::string&)> replacer)
+		{
+			if(index > -1)
+				return walker->do_replace_expansion(name, replacer, index);
+			else
+				return walker->do_array_replace_expansion(name, replacer);
+		}
 	}
 }
 
@@ -582,48 +590,53 @@ var_expansion returns[std::string libbash_value]
 			libbash_value = boost::lexical_cast<std::string>(walker->get_array_length(libbash_name));
 		}
 	))
-	|^(REPLACE_ALL var_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) {
-		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_all,
-															   std::placeholders::_1,
-															   replace_pattern,
-															   libbash_word),
-													 $var_name.index);
-	}
-	|^(REPLACE_AT_END var_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) {
+	|^(REPLACE_ALL var_or_array_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) {
+		libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index,
+												std::bind(&interpreter::replace_all,
+													std::placeholders::_1,
+													replace_pattern,
+													libbash_word));
+	}
+	|^(REPLACE_AT_END var_or_array_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) {
 		replace_pattern = sregex(replace_pattern >> eos);
-		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_all,
-															   std::placeholders::_1,
-															   replace_pattern,
-															   libbash_word),
-													 $var_name.index);
+		libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index,
+												std::bind(&interpreter::replace_all,
+													std::placeholders::_1,
+													replace_pattern,
+													libbash_word));
 	}
-	|^(LAZY_REMOVE_AT_END var_name bash_pattern[replace_pattern, false] (libbash_word=raw_string)?) {
+	|^(LAZY_REMOVE_AT_END var_or_array_name bash_pattern[replace_pattern, false] (libbash_word=raw_string)?) {
 		replace_pattern = sregex(bos >> (s1=*_) >> replace_pattern >> eos);
-		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::lazy_remove_at_end,
-															   std::placeholders::_1,
-															   replace_pattern),
-													 $var_name.index);
+		libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index,
+												std::bind(&interpreter::lazy_remove_at_end,
+													std::placeholders::_1,
+													replace_pattern));
 	}
 	|^((REPLACE_AT_START { greedy = true; }|LAZY_REMOVE_AT_START { greedy = false; })
-		var_name bash_pattern[replace_pattern, greedy] (libbash_word=raw_string)?) {
+		var_or_array_name bash_pattern[replace_pattern, greedy] (libbash_word=raw_string)?) {
 		replace_pattern = sregex(bos >> replace_pattern);
-		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_all,
-															   std::placeholders::_1,
-															   replace_pattern,
-															   libbash_word),
-													 $var_name.index);
+		libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index,
+												std::bind(&interpreter::replace_all,
+													std::placeholders::_1,
+													replace_pattern,
+													libbash_word));
+	}
+	|^(REPLACE_FIRST var_or_array_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) {
+		libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index,
+												std::bind(&interpreter::replace_first,
+													std::placeholders::_1,
+													replace_pattern,
+													libbash_word));
+	};
+
+var_or_array_name returns[std::string libbash_value, int index]
+	:libbash_string=array_name {
+		$libbash_value = libbash_string;
+		$index = -1;
 	}
-	|^(REPLACE_FIRST var_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) {
-		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_first,
-															   std::placeholders::_1,
-															   replace_pattern,
-															   libbash_word),
-													 $var_name.index);
+	|var_name {
+		$libbash_value = $var_name.libbash_value;
+		$index = $var_name.index;
 	};
 
 word returns[std::string libbash_value]

diff --git a/scripts/var_expansion.bash b/scripts/var_expansion.bash
index 97e9587..9ba4286 100644
--- a/scripts/var_expansion.bash
+++ b/scripts/var_expansion.bash
@@ -79,6 +79,17 @@ echo ${FOO039/*(l)}
 echo ${FOO039/?(l)}
 echo ${FOO039/@([a-c]|[k-m])}
 echo ${FOO039//@([a-c]|[k-m])}
+FOO40=("foo bar" foo bar foobar)
+FOO40=("foo bar foo" bar foo foobar)
+echo ${FOO40[@]/foo/poo}
+echo ${FOO40[@]//foo/poo}
+echo ${FOO40[@]#foo}
+echo ${FOO40[@]##f*o}
+echo ${FOO40[@]%foo}
+echo ${FOO40[@]%%f*o}
+echo ${FOO40[@]/#foo}
+echo ${FOO40[@]/%foo}
+echo ${FOO40[@]}
 target="abc123abc"
 echo "${target##+(ab[c])*([[:digit:]])}"
 function positional_parameter_test(){

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 1b8ef0a..274d01d 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -244,6 +244,16 @@ std::string interpreter::do_replace_expansion(const std::string& name,
   return value;
 }
 
+std::string interpreter::do_array_replace_expansion(const std::string& name,
+                                                    std::function<void(std::string&)> replacer) const
+{
+  std::vector<std::string> array;
+  resolve_array<std::string>(name, array);
+  for(auto i = array.begin(); i != array.end(); ++i)
+    replacer(*i);
+  return boost::algorithm::join(array, resolve<std::string>("IFS").substr(0, 1));
+}
+
 std::string::size_type interpreter::get_length(const std::string& name,
                                  const unsigned index) const
 {

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 3c6dde6..0feadef 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -514,7 +514,7 @@ public:
                                           int length) const;
 
   /// \brief perform replacement expansion
-  /// \param name the name of the varaible that needs to be expanded
+  /// \param name the name of the variable that needs to be expanded
   /// \param replacer the function object used to perform expansion
   /// \param index array index, use index=0 if it's not an array
   /// \return the expanded value
@@ -522,6 +522,13 @@ public:
                                    std::function<void(std::string&)> replacer,
                                    const unsigned index) const;
 
+  /// \brief perform array replacement expansion
+  /// \param name the name of the array that needs to be expanded
+  /// \param replacer the function object used to perform expansion
+  /// \return the expanded value
+  std::string do_array_replace_expansion(const std::string& name,
+                                   std::function<void(std::string&)> replacer) const;
+
   /// \brief get the length of a string variable
   /// \param name the name of the variable
   /// \param index the index of the variable


^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-08-04 13:53 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-08-04 13:53 UTC (permalink / raw
  To: gentoo-commits

commit:     9bfb2dbd4180e1171db2026fb58646045c1e7144
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Thu Jul 28 11:50:44 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Tue Aug  2 07:52:19 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=9bfb2dbd

Walker: support expansions without colon

---
 bashast/libbashWalker.g    |   29 ++++++++++++++++++++++++++---
 scripts/var_expansion.bash |   18 ++++++++++++++++++
 src/core/interpreter.h     |   19 +++++++++----------
 3 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index fc05b91..bfcb73b 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -475,13 +475,36 @@ var_expansion returns[std::string libbash_value]
 	bool greedy;
 }
 	:^(USE_DEFAULT_WHEN_UNSET_OR_NULL var_name libbash_word=raw_string) {
-		libbash_value = walker->do_default_expansion($var_name.libbash_value, libbash_word, $var_name.index);
+		libbash_value = walker->do_default_expansion(walker->is_unset_or_null($var_name.libbash_value, $var_name.index),
+													 $var_name.libbash_value,
+													 libbash_word,
+													 $var_name.index);
+	}
+	|^(USE_DEFAULT_WHEN_UNSET var_name libbash_word=raw_string) {
+		libbash_value = walker->do_default_expansion(walker->is_unset($var_name.libbash_value),
+													 $var_name.libbash_value,
+													 libbash_word,
+													 $var_name.index);
 	}
 	|^(ASSIGN_DEFAULT_WHEN_UNSET_OR_NULL var_name libbash_word=raw_string) {
-		libbash_value = walker->do_assign_expansion($var_name.libbash_value, libbash_word, $var_name.index);
+		libbash_value = walker->do_assign_expansion(walker->is_unset_or_null($var_name.libbash_value, $var_name.index),
+													$var_name.libbash_value,
+													libbash_word,
+													$var_name.index);
+	}
+	|^(ASSIGN_DEFAULT_WHEN_UNSET var_name libbash_word=raw_string) {
+		libbash_value = walker->do_assign_expansion(walker->is_unset($var_name.libbash_value),
+													$var_name.libbash_value,
+													libbash_word,
+													$var_name.index);
 	}
 	|^(USE_ALTERNATE_WHEN_UNSET_OR_NULL var_name libbash_word=raw_string) {
-		libbash_value = walker->do_alternate_expansion($var_name.libbash_value, libbash_word, $var_name.index);
+		libbash_value = walker->do_alternate_expansion(walker->is_unset_or_null($var_name.libbash_value, $var_name.index),
+		                                               libbash_word);
+	}
+	|^(USE_ALTERNATE_WHEN_UNSET var_name libbash_word=raw_string) {
+		libbash_value = walker->do_alternate_expansion(walker->is_unset($var_name.libbash_value),
+		                                               libbash_word);
 	}
 	|(^(OFFSET array_name arithmetics arithmetics)) => ^(OFFSET libbash_name=array_name offset=arithmetics length=arithmetics) {
 		libbash_value = walker->do_subarray_expansion(libbash_name, offset, length);

diff --git a/scripts/var_expansion.bash b/scripts/var_expansion.bash
index f1f5e52..2d9a28e 100644
--- a/scripts/var_expansion.bash
+++ b/scripts/var_expansion.bash
@@ -109,3 +109,21 @@ echo $#
 echo a{b,c}d
 echo a{a,bc}d{e,}f
 echo a{ab,cd}d{ef,gh}
+foo=
+unset bar
+echo ${foo-abc}
+foo=
+unset bar
+echo ${foo+abc}
+foo=
+unset bar
+echo ${foo=abc}
+foo=
+unset bar
+echo ${bar-abc}
+foo=
+unset bar
+echo ${bar+abc}
+foo=
+unset bar
+echo ${bar=abc}

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 1ee02dd..091d4b7 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -372,12 +372,12 @@ public:
   /// \param value the value of the word
   /// \param index the index of the paramter
   /// \return the expansion result
-  const std::string do_default_expansion(const std::string& name,
+  const std::string do_default_expansion(bool cond,
+                                         const std::string& name,
                                          const std::string& value,
                                          const unsigned index) const
   {
-    return (is_unset_or_null(name, index)?
-        value : resolve<std::string>(name, index));
+    return (cond ? value : resolve<std::string>(name, index));
   }
 
   /// \brief perform ${parameter:=word} expansion
@@ -385,12 +385,12 @@ public:
   /// \param value the value of the word
   /// \param index the index of the paramter
   /// \return the expansion result
-  const std::string do_assign_expansion(const std::string& name,
+  const std::string do_assign_expansion(bool cond,
+                                        const std::string& name,
                                         const std::string& value,
                                         const unsigned index)
   {
-    return (is_unset_or_null(name, index)?
-        set_value(name, value, index) : resolve<std::string>(name, index));
+    return (cond ? set_value(name, value, index) : resolve<std::string>(name, index));
   }
 
   /// \brief perform ${parameter:+word} expansion
@@ -398,11 +398,10 @@ public:
   /// \param value the value of the word
   /// \param index the index of the paramter
   /// \return the expansion result
-  const std::string do_alternate_expansion(const std::string& name,
-                                           const std::string& value,
-                                           const unsigned index) const
+  const std::string do_alternate_expansion(bool cond,
+                                           const std::string& value) const
   {
-    return (is_unset_or_null(name, index)? "" : value);
+    return (cond ? "" : value);
   }
 
   /// \brief perform substring expansion



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-06-09  8:15 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-06-09  8:15 UTC (permalink / raw
  To: gentoo-commits

commit:     17556b103a2817bfacb4a838f07e8d3738caed8d
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Sat Jun  4 10:20:04 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Thu Jun  9 08:39:00 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=17556b10

Walker: support != in arithmetic expansion

---
 bashast/libbashWalker.g                   |    1 +
 scripts/arithmetic_assignment.bash        |    1 +
 scripts/arithmetic_assignment.bash.result |    1 +
 src/core/interpreter.h                    |    9 +++++++++
 4 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 8263b15..e793f56 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -903,6 +903,7 @@ arithmetics returns[int value]
 	|^(GEQ l=arithmetics r=arithmetics) { $value = walker->greater_equal_than(l, r); }
 	|^(LESS_THAN l=arithmetics r=arithmetics) { $value = walker->less_than(l, r); }
 	|^(GREATER_THAN l=arithmetics r=arithmetics) { $value = walker->greater_than(l, r); }
+	|^(NOT_EQUALS l=arithmetics r=arithmetics) { $value = walker->not_equal_to(l, r); }
 	|^(LSHIFT l=arithmetics r=arithmetics) { $value = walker->left_shift(l, r); }
 	|^(RSHIFT l=arithmetics r=arithmetics) { $value = walker->right_shift(l, r); }
 	|^(PLUS l=arithmetics r=arithmetics) { $value = walker->plus(l, r); }

diff --git a/scripts/arithmetic_assignment.bash b/scripts/arithmetic_assignment.bash
index f1f40f6..c53758c 100644
--- a/scripts/arithmetic_assignment.bash
+++ b/scripts/arithmetic_assignment.bash
@@ -11,5 +11,6 @@ FOO009="$((value^=5))"
 FOO010="$((value|=10))"
 FOO011=("CREATED" 2)
 FOO012="$((${FOO011[0]}=10))"
+FOO013="$((3!=5))"
 value=100
 let "value=${value}"

diff --git a/scripts/arithmetic_assignment.bash.result b/scripts/arithmetic_assignment.bash.result
index 9f47242..d5e6ea4 100644
--- a/scripts/arithmetic_assignment.bash.result
+++ b/scripts/arithmetic_assignment.bash.result
@@ -11,4 +11,5 @@ FOO009=5
 FOO010=15
 FOO011=CREATED 2
 FOO012=10
+FOO013=1
 value=100

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 2c138e5..39fcadf 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -267,6 +267,15 @@ public:
     return left > right;
   }
 
+  /// \brief perform not equal to
+  /// \param the first operand
+  /// \param the second operand
+  /// \return the calculated result
+  static int not_equal_to(int left, int right)
+  {
+    return left != right;
+  }
+
   /// \brief perform left shift
   /// \param the first operand
   /// \param the second operand



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-06-03 14:48 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-06-03 14:48 UTC (permalink / raw
  To: gentoo-commits

commit:     5619617d2f23057f07fee8766998d8e01bc1a644
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Wed Jun  1 14:55:14 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri Jun  3 12:53:53 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=5619617d

Walker: support output redirection

We only support redirections for bash built-ins for now.

---
 bashast/libbashWalker.g               |   49 +++++++++++++++++++++++++++------
 scripts/command_execution.bash        |    2 +-
 scripts/command_execution.bash.result |    1 -
 src/core/interpreter.h                |   14 +++++++--
 4 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 58de4b7..1e6f94b 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -40,6 +40,7 @@ options
 
 @postinclude{
 
+	#include <fstream>
 	#include <iostream>
 	#include <sstream>
 
@@ -466,10 +467,16 @@ simple_command
 execute_command[const std::string& name, std::vector<std::string>& libbash_args]
 @declarations {
 	interpreter::local_scope current_scope(*walker);
+	std::unique_ptr<std::ostream> out;
+	std::unique_ptr<std::ostream> err;
+	std::unique_ptr<std::istream> in;
+	bool redirection = false;
 }
-	:var_def[true]* redirect* {
+	:var_def[true]* (redirect[out, err, in]{ redirection = true; })* {
 		if(walker->has_function(name))
 		{
+			if(redirection)
+				std::cerr << "We do not support redirection for function calls." << std::endl;
 			ANTLR3_MARKER command_index = INDEX();
 			try
 			{
@@ -485,7 +492,7 @@ execute_command[const std::string& name, std::vector<std::string>& libbash_args]
 		}
 		else if(cppbash_builtin::is_builtin(name))
 		{
-			walker->set_status(walker->execute_builtin(name, libbash_args));
+			walker->set_status(walker->execute_builtin(name, libbash_args, out.get(), err.get(), in.get()));
 		}
 		else if(name == "export")
 		{
@@ -500,21 +507,45 @@ execute_command[const std::string& name, std::vector<std::string>& libbash_args]
 	}
 	(BANG { walker->set_status(!walker->get_status()); })?;
 
-redirect
-	:^(REDIR redirect_operator redirect_destination) {
+redirect[std::unique_ptr<std::ostream>& out, std::unique_ptr<std::ostream>& err, std::unique_ptr<std::istream>& in]
+	:^(REDIR LESS_THAN redirect_destination_input[in]) {
+		std::cerr << "Redirection is not supported yet" << std::endl;
+	}
+	|^(REDIR GREATER_THAN redirect_destination_output[out])
+	|^(REDIR DIGIT LESS_THAN redirect_destination_input[in]) {
+		std::cerr << "Redirection is not supported yet" << std::endl;
+	}
+	|^(REDIR DIGIT GREATER_THAN redirect_destination_output[out]) {
 		std::cerr << "Redirection is not supported yet" << std::endl;
 	};
 
-redirect_destination
-	:string_expr //path to a file
-	|FILE_DESCRIPTOR DIGIT
-	|FILE_DESCRIPTOR_MOVE DIGIT;
-
 redirect_operator
 	:LESS_THAN
 	|GREATER_THAN
 	|FILE_DESCRIPTOR DIGIT redirect_operator;
 
+redirect_destination_output[std::unique_ptr<std::ostream>& out]
+	:string_expr {
+		out.reset(new std::ofstream($string_expr.libbash_value, std::ofstream::trunc));
+	}
+	|FILE_DESCRIPTOR DIGIT {
+		std::cerr << "FILE_DESCRIPTOR redirection is not supported yet" << std::endl;
+	}
+	|FILE_DESCRIPTOR_MOVE DIGIT {
+		std::cerr << "FILE_DESCRIPTOR_MOVE redirection is not supported yet" << std::endl;
+	};
+
+redirect_destination_input[std::unique_ptr<std::istream>& in]
+	:string_expr {
+		std::cerr << "Input redirection for file is not supported yet" << std::endl;
+	}
+	|FILE_DESCRIPTOR DIGIT {
+		std::cerr << "FILE_DESCRIPTOR redirection is not supported yet" << std::endl;
+	}
+	|FILE_DESCRIPTOR_MOVE DIGIT {
+		std::cerr << "FILE_DESCRIPTOR_MOVE redirection is not supported yet" << std::endl;
+	};
+
 argument[std::vector<std::string>& args]
 	: string_expr {
 		if($string_expr.quoted)

diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash
index 8005a23..a500b63 100644
--- a/scripts/command_execution.bash
+++ b/scripts/command_execution.bash
@@ -19,7 +19,7 @@ FOO="abc" echo "command environment"
 export FOO003=1 FOO004=abc FOO005=(1 2 3) FOO002
 export foo
 abc=1 export foo
-true > /dev/null
+echo "hi" > /dev/null
 
 function unset_inner()
 {

diff --git a/scripts/command_execution.bash.result b/scripts/command_execution.bash.result
index d47650d..e0bf724 100644
--- a/scripts/command_execution.bash.result
+++ b/scripts/command_execution.bash.result
@@ -5,7 +5,6 @@ right
 end
 command environment
 We do not support command env before the export builtin.
-Redirection is not supported yet
 FOO006=1 in unset_outer
 FOO007= in unset_outer
 FOO006= in unset_outer

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 3420ee4..2c5f383 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -574,9 +574,17 @@ public:
   /// \param builtin arguments
   /// \return the return value of the builtin
   int execute_builtin(const std::string& name,
-                      const std::vector<std::string>& args)
-  {
-    return cppbash_builtin::exec(name, args, *out, *err, *in, *this);
+                      const std::vector<std::string>& args,
+                      std::ostream* output=0,
+                      std::ostream* error=0,
+                      std::istream* input=0)
+  {
+    return cppbash_builtin::exec(name,
+                                 args,
+                                 output == 0 ? *out : *output,
+                                 error == 0 ? *err : *error,
+                                 input == 0 ? *in : *input,
+                                 *this);
   }
 
   /// \brief perform ${parameter:−word} expansion



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-05-15 11:19 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-05-15 11:19 UTC (permalink / raw
  To: gentoo-commits

commit:     d869ca70e03de7a07d041900592e8b3af2b2a562
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Sun May 15 06:08:10 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Sun May 15 10:40:51 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=d869ca70

Walker: fix a bug in command stack handling

All commands, built-ins and functions should have their own local
scope(or command environment). Take "foo=abc bar" for example, the
variable foo need to be stored in local scope. We only cared about
the local scope for functions, which caused the example crash. Now
it's fixed by creating local scopes in the walker grammar.

---
 bashast/libbashWalker.g               |   18 ++++++++++++------
 scripts/command_execution.bash        |    1 +
 scripts/command_execution.bash.result |    1 +
 src/core/interpreter.cpp              |    6 +-----
 src/core/interpreter.h                |   20 ++++++++++++++++++++
 5 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 5b22e7a..bd87ee8 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -439,13 +439,19 @@ simple_command
 @declarations {
 	std::vector<std::string> libbash_args;
 }
-	:^(COMMAND string_expr (argument[libbash_args])* var_def[true]*) {
-		if(walker->has_function($string_expr.libbash_value))
+	:^(COMMAND string_expr (argument[libbash_args])* execute_command[$string_expr.libbash_value, libbash_args]);
+
+execute_command[const std::string& name, std::vector<std::string>& libbash_args]
+@declarations {
+	interpreter::local_scope current_scope(*walker);
+}
+	:var_def[true]* {
+		if(walker->has_function(name))
 		{
 			ANTLR3_MARKER command_index = INDEX();
 			try
 			{
-				walker->set_status(walker->call($string_expr.libbash_value,
+				walker->set_status(walker->call(name,
 												libbash_args,
 												ctx,
 												compound_command));
@@ -455,13 +461,13 @@ simple_command
 				SEEK(command_index);
 			}
 		}
-		else if(cppbash_builtin::is_builtin($string_expr.libbash_value))
+		else if(cppbash_builtin::is_builtin(name))
 		{
-			walker->set_status(walker->execute_builtin($string_expr.libbash_value, libbash_args));
+			walker->set_status(walker->execute_builtin(name, libbash_args));
 		}
 		else
 		{
-			std::cerr << $string_expr.libbash_value << " is not supported yet" << std::endl;
+			std::cerr << name << " is not supported yet" << std::endl;
 			walker->set_status(1);
 		}
 	};

diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash
index 3664356..821d061 100644
--- a/scripts/command_execution.bash
+++ b/scripts/command_execution.bash
@@ -13,3 +13,4 @@ false && echo "wrong"
 false || echo "right"
 true || echo "wrong"
 echo "end"
+FOO="abc" echo "command environment"

diff --git a/scripts/command_execution.bash.result b/scripts/command_execution.bash.result
index d9f3021..8bd7226 100644
--- a/scripts/command_execution.bash.result
+++ b/scripts/command_execution.bash.result
@@ -3,5 +3,6 @@ hello world
 right
 right
 end
+command environment
 FOO001=hello
 FOO002=Hello World

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 1102138..2214613 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -206,8 +206,7 @@ int interpreter::call(const std::string& name,
     return -1;
   func_index = iter->second;
 
-  // Prepare function stack and arguments
-  local_members.push_back(scope());
+  // Prepare arguments
   define_function_arguments(local_members.back(), arguments);
 
   auto INPUT = ctx->pTreeParser->ctnstream;
@@ -221,9 +220,6 @@ int interpreter::call(const std::string& name,
   // Reset to the previous index
   ISTREAM->seek(ISTREAM, curr);
 
-  // Clear function stack
-  local_members.pop_back();
-
   return 0;
 }
 

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index d71885a..c46afe1 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -87,6 +87,26 @@ class interpreter
 
 public:
 
+  ///
+  /// \class local_scope
+  /// \brief RAII concept for local scope management
+  ///
+  class local_scope
+  {
+    interpreter& walker;
+
+  public:
+    local_scope(interpreter& w): walker(w)
+    {
+      walker.local_members.push_back(scope());
+    }
+
+    ~local_scope()
+    {
+      walker.local_members.pop_back();
+    }
+  };
+
   interpreter(): out(&std::cout), err(&std::cerr), in(&std::cin)
   {
     define("IFS", " \t\n");



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-05-11  7:19 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-05-11  7:19 UTC (permalink / raw
  To: gentoo-commits

commit:     eaeae33594b008cc3305346d9b1e1e0162b8cd46
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Mon May  9 12:43:41 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed May 11 06:53:16 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=eaeae335

Walker: support patterns in variable expansion

---
 bashast/libbashWalker.g           |   55 ++++++++++++++++++++-----------------
 scripts/var_expansion.bash        |   10 +++++++
 scripts/var_expansion.bash.result |   10 +++++++
 src/core/interpreter.cpp          |   49 +++++++++++---------------------
 src/core/interpreter.h            |   33 ++++------------------
 5 files changed, 73 insertions(+), 84 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index c3ef8ac..e80e43e 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -204,7 +204,7 @@ string_part returns[std::string libbash_value, bool quoted]
 		$libbash_value = libbash_string;
 	});
 
-bash_pattern[boost::xpressive::sregex& pattern]
+bash_pattern[boost::xpressive::sregex& pattern, bool greedy]
 @declarations {
 	using namespace boost::xpressive;
 	bool do_append = false;
@@ -217,7 +217,10 @@ bash_pattern[boost::xpressive::sregex& pattern]
 				append($pattern, as_xpr(libbash_string), do_append);
 			})*)
 		|(MATCH_ALL) => MATCH_ALL {
-			append($pattern, *_, do_append);
+			if($greedy)
+				append($pattern, *_, do_append);
+			else
+				append($pattern, -*_, do_append);
 		}
 		|(MATCH_ONE) => MATCH_ONE {
 			append($pattern, _, do_append);
@@ -292,6 +295,11 @@ var_name returns[std::string libbash_value, unsigned index]
 	};
 
 var_expansion returns[std::string libbash_value]
+@declarations {
+	using namespace boost::xpressive;
+	sregex replace_pattern;
+	bool greedy;
+}
 	:^(USE_DEFAULT_WHEN_UNSET_OR_NULL var_name libbash_word=word) {
 		libbash_value = walker->do_default_expansion($var_name.libbash_value, libbash_word, $var_name.index);
 	}
@@ -315,50 +323,47 @@ var_expansion returns[std::string libbash_value]
 			libbash_value = boost::lexical_cast<std::string>(walker->get_array_length(libbash_name));
 		}
 	))
-	|^(REPLACE_ALL var_name replace_pattern=string_expr (replacement=string_expr)?) {
+	|^(REPLACE_ALL var_name bash_pattern[replace_pattern, true] (replacement=string_expr)?) {
 		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
 													 std::bind(&interpreter::replace_all,
 															   std::placeholders::_1,
-															   replace_pattern.libbash_value,
+															   replace_pattern,
 															   replacement.libbash_value),
 													 $var_name.index);
 	}
-	|^(REPLACE_AT_END var_name replace_pattern=string_expr (replacement=string_expr)?) {
+	|^(REPLACE_AT_END var_name bash_pattern[replace_pattern, true] (replacement=string_expr)?) {
+		replace_pattern = sregex(replace_pattern >> eos);
 		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_at_end,
+													 std::bind(&interpreter::replace_all,
 															   std::placeholders::_1,
-															   replace_pattern.libbash_value,
+															   replace_pattern,
 															   replacement.libbash_value),
 													 $var_name.index);
 	}
-	|^(REPLACE_AT_START var_name replace_pattern=string_expr (replacement=string_expr)?) {
+	|^(LAZY_REMOVE_AT_END var_name bash_pattern[replace_pattern, false] (replacement=string_expr)?) {
+		replace_pattern = sregex(bos >> (s1=*_) >> replace_pattern >> eos);
 		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_at_start,
+													 std::bind(&interpreter::lazy_remove_at_end,
 															   std::placeholders::_1,
-															   replace_pattern.libbash_value,
-															   replacement.libbash_value),
+															   replace_pattern),
 													 $var_name.index);
 	}
-	|^(REPLACE_FIRST var_name replace_pattern=string_expr (replacement=string_expr)?) {
+	|^((REPLACE_AT_START { greedy = true; }|LAZY_REMOVE_AT_START { greedy = false; })
+		var_name bash_pattern[replace_pattern, greedy] (replacement=string_expr)?) {
+		replace_pattern = sregex(bos >> replace_pattern);
 		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::replace_first,
+													 std::bind(&interpreter::replace_all,
 															   std::placeholders::_1,
-															   replace_pattern.libbash_value,
+															   replace_pattern,
 															   replacement.libbash_value),
 													 $var_name.index);
 	}
-	|^(LAZY_REMOVE_AT_START var_name replace_pattern=string_expr) {
-		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::lazy_remove_at_start,
-															   std::placeholders::_1,
-															   replace_pattern.libbash_value),
-													 $var_name.index);
-	}
-	|^(LAZY_REMOVE_AT_END var_name replace_pattern=string_expr) {
+	|^(REPLACE_FIRST var_name bash_pattern[replace_pattern, true] (replacement=string_expr)?) {
 		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
-													 std::bind(&interpreter::lazy_remove_at_end,
+													 std::bind(&interpreter::replace_first,
 															   std::placeholders::_1,
-															   replace_pattern.libbash_value),
+															   replace_pattern,
+															   replacement.libbash_value),
 													 $var_name.index);
 	};
 
@@ -633,7 +638,7 @@ case_clause[const std::string& target] returns[bool matched]
 @declarations {
 	std::vector<boost::xpressive::sregex> patterns;
 }
-	:^(CASE_PATTERN ( { patterns.push_back(boost::xpressive::sregex()); } bash_pattern[patterns.back()])+ {
+	:^(CASE_PATTERN ( { patterns.push_back(boost::xpressive::sregex()); } bash_pattern[patterns.back(), true])+ {
 		if(LA(1) == CASE_COMMAND)
 		{
 			// omit CASE_COMMAND

diff --git a/scripts/var_expansion.bash b/scripts/var_expansion.bash
index 5ebd63e..7a371b3 100644
--- a/scripts/var_expansion.bash
+++ b/scripts/var_expansion.bash
@@ -60,3 +60,13 @@ FOO058=${FOO039%world}
 FOO059=${FOO039%%world}
 FOO060=${FOO039%World}
 FOO061=${FOO039%%World}
+FOO062=${FOO039#Hel*}
+FOO063=${FOO039##Hel*}
+FOO064=${FOO039%*rld}
+FOO065=${FOO039%%*rld}
+FOO066=${FOO039/l/r}
+FOO067=${FOO039//l/r}
+FOO068=${FOO039/#He/he}
+FOO069=${FOO039/#ello/i}
+FOO070=${FOO039/%ld/d}
+FOO071=${FOO039/%rl/r}

diff --git a/scripts/var_expansion.bash.result b/scripts/var_expansion.bash.result
index 50fd5d5..a1fe905 100644
--- a/scripts/var_expansion.bash.result
+++ b/scripts/var_expansion.bash.result
@@ -62,3 +62,13 @@ FOO058=Hello World
 FOO059=Hello World
 FOO060=Hello 
 FOO061=Hello 
+FOO062=lo World
+FOO063=
+FOO064=Hello Wo
+FOO065=
+FOO066=Herlo World
+FOO067=Herro Worrd
+FOO068=hello World
+FOO069=Hello World
+FOO070=Hello Word
+FOO071=Hello World

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index aa6c4de..1102138 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -228,48 +228,33 @@ int interpreter::call(const std::string& name,
 }
 
 void interpreter::replace_all(std::string& value,
-                              const std::string& pattern,
+                              const boost::xpressive::sregex& pattern,
                               const std::string& replacement)
 {
-  boost::replace_all(value, pattern, replacement);
+  value = boost::xpressive::regex_replace(value,
+                                          pattern,
+                                          replacement,
+                                          boost::xpressive::regex_constants::format_literal);
 }
 
-void interpreter::replace_at_end(std::string& value,
-                                 const std::string& pattern,
-                                 const std::string& replacement)
-{
-  if(value.size() >= pattern.size() &&
-     value.substr(value.size() - pattern.size()) == pattern)
-    value.replace(value.size() - pattern.size(),
-                  pattern.size(),
-                  replacement);
-}
-
-void interpreter::replace_at_start(std::string& value,
-                                   const std::string& pattern,
-                                   const std::string& replacement)
+void interpreter::lazy_remove_at_end(std::string& value,
+                              const boost::xpressive::sregex& pattern)
 {
-  if(value.substr(0, pattern.size()) == pattern)
-    value.replace(0, pattern.size(), replacement);
+  boost::xpressive::smatch what;
+  if(boost::xpressive::regex_match(value,
+                                   what,
+                                   pattern))
+    value = what[1];
 }
 
 void interpreter::replace_first(std::string& value,
-                                const std::string& pattern,
+                                const boost::xpressive::sregex& pattern,
                                 const std::string& replacement)
 {
-  boost::replace_first(value, pattern, replacement);
-}
-
-void interpreter::lazy_remove_at_start(std::string& value,
-                                       const std::string& pattern)
-{
-  replace_at_start(value, pattern, "");
-}
-
-void interpreter::lazy_remove_at_end(std::string& value,
-                                     const std::string& pattern)
-{
-  replace_at_end(value, pattern, "");
+  value = boost::xpressive::regex_replace(value,
+                                          pattern,
+                                          replacement,
+                                          boost::xpressive::regex_constants::format_literal | boost::xpressive::regex_constants::format_first_only);
 }
 
 void interpreter::trim_trailing_eols(std::string& value)

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 7673479..d71885a 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -32,6 +32,7 @@
 #include <string>
 
 #include <antlr3basetree.h>
+#include <boost/xpressive/xpressive.hpp>
 
 #include "core/symbols.hpp"
 #include "cppbash_builtin.h"
@@ -637,45 +638,23 @@ public:
   /// \param the pattern used to match the value
   /// \param the replacement string
   static void replace_all(std::string& value,
-                          const std::string& pattern,
+                          const boost::xpressive::sregex& pattern,
                           const std::string& replacement);
 
-  /// \brief perform expansion like ${var/%foo/bar}
-  /// \param the value to be expanded
-  /// \param the pattern used to match the value
-  /// \param the replacement string
-  static void replace_at_end(std::string& value,
-                             const std::string& pattern,
-                             const std::string& replacement);
-
-  /// \brief perform expansion like ${var/#foo/bar}
+  /// \brief perform expansion like ${var%foo}
   /// \param the value to be expanded
   /// \param the pattern used to match the value
-  /// \param the replacement string
-  static void replace_at_start(std::string& value,
-                               const std::string& pattern,
-                               const std::string& replacement);
+  static void lazy_remove_at_end(std::string& value,
+                                 const boost::xpressive::sregex& pattern);
 
   /// \brief perform expansion like ${var/foo/bar}
   /// \param the value to be expanded
   /// \param the pattern used to match the value
   /// \param the replacement string
   static void replace_first(std::string& value,
-                            const std::string& pattern,
+                            const boost::xpressive::sregex& pattern,
                             const std::string& replacement);
 
-  /// \brief perform expansion like ${var#foo}
-  /// \param the value to be expanded
-  /// \param the pattern used to match the value
-  static void lazy_remove_at_start(std::string& value,
-                                   const std::string& pattern);
-
-  /// \brief perform expansion like ${var%foo}
-  /// \param the value to be expanded
-  /// \param the pattern used to match the value
-  static void lazy_remove_at_end(std::string& value,
-                                 const std::string& pattern);
-
   /// \brief remove trailing EOLs from the value
   /// \param[in, out] the target
   static void trim_trailing_eols(std::string& value);



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-05-07 12:25 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-05-07 12:25 UTC (permalink / raw
  To: gentoo-commits

commit:     45746a47c5205d0b4f3729ef9fa9373894733c8c
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Thu May  5 13:26:54 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Sat May  7 12:13:40 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=45746a47

Walker: support defining local variables

---
 bashast/libbashWalker.g          |   20 ++++++++++++++----
 scripts/function_def.bash        |   10 +++++++++
 scripts/function_def.bash.result |    1 +
 src/core/interpreter.cpp         |   40 +++++++++++++++++++++++++++++++++----
 src/core/interpreter.h           |   39 +++++++++++++++++++++---------------
 5 files changed, 84 insertions(+), 26 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 064556a..1a305ef 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -91,7 +91,11 @@ start: list|EOF;
 
 list: ^(LIST (function_def|logic_command_list)+);
 
-variable_definitions: ^(VARIABLE_DEFINITIONS var_def+);
+variable_definitions
+@declarations {
+	bool local = false;
+}
+	:^(VARIABLE_DEFINITIONS (LOCAL { local = true; })? var_def[local]+);
 
 name_base returns[std::string libbash_value]
 	:NAME { $libbash_value = walker->get_string($NAME); }
@@ -115,13 +119,16 @@ options{ k=1; }
 	:DIGIT { $libbash_value = walker->get_string($DIGIT); }
 	|NUMBER { $libbash_value = walker->get_string($NUMBER); };
 
-var_def
+var_def[bool local]
 @declarations {
 	std::map<int, std::string> values;
 	unsigned index = 0;
 }
 	:^(EQUALS name string_expr?) {
-		walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index);
+		if(local)
+			walker->define_local($name.libbash_value, $string_expr.libbash_value, false, $name.index);
+		else
+			walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index);
 	}
 	|^(EQUALS libbash_name=name_base ^(ARRAY (
 										(expr=string_expr
@@ -130,7 +137,10 @@ var_def
 											} expr=string_expr))
 										{ values[index++] = expr.libbash_value; })*
 									 )){
-		walker->define(libbash_name, values);
+		if(local)
+			walker->define_local(libbash_name, values);
+		else
+			walker->define(libbash_name, values);
 	};
 
 string_expr returns[std::string libbash_value, bool quoted]
@@ -282,7 +292,7 @@ simple_command
 @declarations {
 	std::vector<std::string> libbash_args;
 }
-	:^(COMMAND string_expr (argument[libbash_args])* var_def*) {
+	:^(COMMAND string_expr (argument[libbash_args])* var_def[true]*) {
 		if(walker->has_function($string_expr.libbash_value))
 		{
 			walker->set_status(walker->call($string_expr.libbash_value,

diff --git a/scripts/function_def.bash b/scripts/function_def.bash
index 194d030..cbce4cd 100644
--- a/scripts/function_def.bash
+++ b/scripts/function_def.bash
@@ -26,3 +26,13 @@ FOO001="4		5"
 ARRAY=(1 2 3)
 func_with_args ${ARRAY[@]} $FOO001
 func_with_args 100 $ARG2 $ARG3 $ARG4
+
+func_nested1() {
+    echo $foo_nested ${bar_nested[0]}
+}
+func_nested2() {
+    local foo_nested=hi bar_nested=(1 2
+    3)
+    func_nested1
+}
+func_nested2

diff --git a/scripts/function_def.bash.result b/scripts/function_def.bash.result
index de9f3f8..bfc30b5 100644
--- a/scripts/function_def.bash.result
+++ b/scripts/function_def.bash.result
@@ -1,3 +1,4 @@
+hi 1
 ARG1=100
 ARG2=2
 ARG3=3

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 5363636..aa6c4de 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -24,6 +24,8 @@
 
 #include "core/interpreter.h"
 
+#include <cctype>
+
 #include <functional>
 
 #include <boost/algorithm/string/classification.hpp>
@@ -31,6 +33,7 @@
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string/trim.hpp>
+#include <boost/foreach.hpp>
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm/copy.hpp>
 
@@ -49,6 +52,33 @@ std::string interpreter::get_string(pANTLR3_BASE_TREE node)
                      token->stop - token->start + 1);
 }
 
+std::shared_ptr<variable> interpreter::resolve_variable(const std::string& name) const
+{
+  if(name.empty())
+    throw interpreter_exception("Variable name shouldn't be empty");
+  // positional parameter
+  if(isdigit(name[0]) && !local_members.empty())
+  {
+    auto iter_local = local_members.back().find(name);
+    if(iter_local != local_members.back().end())
+      return iter_local->second;
+  }
+  else
+  {
+    BOOST_REVERSE_FOREACH(auto& frame, local_members)
+    {
+      auto iter_local = frame.find(name);
+      if(iter_local != frame.end())
+        return iter_local->second;
+    }
+  }
+
+  auto iter_global = members.find(name);
+  if(iter_global == members.end())
+    return std::shared_ptr<variable>();
+  return iter_global->second;
+}
+
 bool interpreter::is_unset_or_null(const std::string& name,
                                    const unsigned index) const
 {
@@ -155,13 +185,13 @@ void interpreter::split_word(const std::string& word, std::vector<std::string>&
   output.insert(output.end(), splitted_values.begin(), splitted_values.end());
 }
 
-inline void define_function_arguments(std::unique_ptr<scope>& current_stack,
+inline void define_function_arguments(scope& current_stack,
                                       const std::vector<std::string>& arguments)
 {
   for(auto i = 0u; i != arguments.size(); ++i)
   {
     const std::string& name = boost::lexical_cast<std::string>(i + 1);
-    (*current_stack)[name] = std::shared_ptr<variable>(new variable(name, arguments[i]));
+    current_stack[name].reset(new variable(name, arguments[i]));
   }
 }
 
@@ -177,8 +207,8 @@ int interpreter::call(const std::string& name,
   func_index = iter->second;
 
   // Prepare function stack and arguments
-  local_members.push(std::unique_ptr<scope>(new scope));
-  define_function_arguments(local_members.top(), arguments);
+  local_members.push_back(scope());
+  define_function_arguments(local_members.back(), arguments);
 
   auto INPUT = ctx->pTreeParser->ctnstream;
   auto ISTREAM = INPUT->tnstream->istream;
@@ -192,7 +222,7 @@ int interpreter::call(const std::string& name,
   ISTREAM->seek(ISTREAM, curr);
 
   // Clear function stack
-  local_members.pop();
+  local_members.pop_back();
 
   return 0;
 }

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 35ae8ac..7673479 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -29,7 +29,6 @@
 
 #include <functional>
 #include <memory>
-#include <stack>
 #include <string>
 
 #include <antlr3basetree.h>
@@ -60,7 +59,7 @@ class interpreter
   /// \var private::local_members
   /// \brief local scope for function arguments, execution environment and
   ///        local variables
-  std::stack<std::unique_ptr<scope>> local_members;
+  std::vector<scope> local_members;
 
   std::ostream* out;
 
@@ -83,6 +82,8 @@ class interpreter
                                const std::string& delim,
                                std::string& result) const;
 
+  std::shared_ptr<variable> resolve_variable(const std::string&) const;
+
 public:
 
   interpreter(): out(&std::cout), err(&std::cerr), in(&std::cin)
@@ -401,17 +402,11 @@ public:
   template <typename T>
   T resolve(const std::string& name, const unsigned index=0) const
   {
-    if(!local_members.empty())
-    {
-      auto iter_local = local_members.top()->find(name);
-      if(iter_local != local_members.top()->end())
-        return iter_local->second->get_value<T>(index);
-    }
-
-    auto iter_global = members.find(name);
-    if(iter_global == members.end())
-      return T();
-    return iter_global->second->get_value<T>(index);
+    auto var = resolve_variable(name);
+    if(var)
+      return var->get_value<T>(index);
+    else
+      return T{};
   }
 
   /// \brief resolve array variable
@@ -495,9 +490,21 @@ public:
               bool readonly=false,
               const unsigned index=0)
   {
-    std::shared_ptr<variable> target(
-        new variable(name, value, readonly, index));
-    members[name] = target;
+    members[name].reset(new variable(name, value, readonly, index));
+  }
+
+  /// \brief define a new local variable
+  /// \param the name of the variable
+  /// \param the value of the variable
+  /// \param whether it's readonly, default is false
+  /// \param whether it's null, default is false
+  template <typename T>
+  void define_local(const std::string& name,
+                    const T& value,
+                    bool readonly=false,
+                    const unsigned index=0)
+  {
+    local_members.back()[name].reset(new variable(name, value, readonly, index));
   }
 
   /// \brief define a new function



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-20 14:04 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-20 14:04 UTC (permalink / raw
  To: gentoo-commits

commit:     8838cef4a07903791881cc64c8c5de02370eb38b
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Tue Apr 19 13:35:06 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Apr 20 13:44:30 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=8838cef4

Walker: implement replacement expansion for raw string

${parameter/pattern/string} is supported for raw string. We haven't
provided any advanced pattern matching yet. Array and positional
parameter expansion like ${var[@]/foo/bar} and ${*/foo/bar} are not
supported for now.

---
 bashast/libbashWalker.g             |   34 +++++++++++++++++++++++++-
 scripts/var_expansion.ebuild        |   15 +++++++++++
 scripts/var_expansion.ebuild.result |   15 +++++++++++
 src/core/interpreter.cpp            |   36 +++++++++++++++++++++++++++
 src/core/interpreter.h              |   46 +++++++++++++++++++++++++++++++++++
 5 files changed, 145 insertions(+), 1 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index b6c9a7f..752e470 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -194,7 +194,39 @@ var_expansion returns[std::string libbash_value]
 		|^(libbash_name=name_base ARRAY_SIZE) {
 			libbash_value = boost::lexical_cast<std::string>(walker->get_array_length(libbash_name));
 		}
-	));
+	))
+	|^(REPLACE_ALL var_name pattern=string_expr (replacement=string_expr)?) {
+		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
+													 std::bind(&interpreter::replace_all,
+															   std::placeholders::_1,
+															   pattern.libbash_value,
+															   replacement.libbash_value),
+													 $var_name.index);
+	}
+	|^(REPLACE_AT_END var_name pattern=string_expr (replacement=string_expr)?) {
+		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
+													 std::bind(&interpreter::replace_at_end,
+															   std::placeholders::_1,
+															   pattern.libbash_value,
+															   replacement.libbash_value),
+													 $var_name.index);
+	}
+	|^(REPLACE_AT_START var_name pattern=string_expr (replacement=string_expr)?) {
+		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
+													 std::bind(&interpreter::replace_at_start,
+															   std::placeholders::_1,
+															   pattern.libbash_value,
+															   replacement.libbash_value),
+													 $var_name.index);
+	}
+	|^(REPLACE_FIRST var_name pattern=string_expr (replacement=string_expr)?) {
+		libbash_value = walker->do_replace_expansion($var_name.libbash_value,
+													 std::bind(&interpreter::replace_first,
+															   std::placeholders::_1,
+															   pattern.libbash_value,
+															   replacement.libbash_value),
+													 $var_name.index);
+	};
 
 word returns[std::string libbash_value]
 	:(num) => libbash_string=num { $libbash_value = libbash_string; }

diff --git a/scripts/var_expansion.ebuild b/scripts/var_expansion.ebuild
index c45ad1e..9a46277 100644
--- a/scripts/var_expansion.ebuild
+++ b/scripts/var_expansion.ebuild
@@ -37,3 +37,18 @@ FOO035="${#ARRAY[0]}"
 FOO036="${#ARRAY[@]}"
 FOO037="${#ARRAY[*]}"
 FOO038="${#ARRAY}"
+FOO039="Hello World"
+FOO040=${FOO039/nothing/nothing}
+FOO041=${FOO039/o W/ow}
+FOO042=${FOO039//o/e}
+FOO043=${FOO039/#He/he}
+FOO044=${FOO039/#he/he}
+FOO045=${FOO039/%rld/rlD}
+FOO046=${FOO039/%rlD/rlD}
+FOO047=${FOO039/o W}
+FOO048=${FOO039//o}
+FOO049=${FOO039/#He}
+FOO050=${FOO039/#he}
+FOO051=${FOO039/%rld}
+FOO052=${FOO039/%rlD}
+FOO053=${FOO039/aaaaaaaaaaaa}

diff --git a/scripts/var_expansion.ebuild.result b/scripts/var_expansion.ebuild.result
index 8bea3b8..ed5fea3 100644
--- a/scripts/var_expansion.ebuild.result
+++ b/scripts/var_expansion.ebuild.result
@@ -39,3 +39,18 @@ FOO035=2
 FOO036=5
 FOO037=5
 FOO038=2
+FOO039=Hello World
+FOO040=Hello World
+FOO041=Helloworld
+FOO042=Helle Werld
+FOO043=hello World
+FOO044=Hello World
+FOO045=Hello WorlD
+FOO046=Hello World
+FOO047=Hellorld
+FOO048=Hell Wrld
+FOO049=llo World
+FOO050=Hello World
+FOO051=Hello Wo
+FOO052=Hello World
+FOO053=Hello World

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index c683315..0ac5699 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -24,8 +24,11 @@
 
 #include "core/interpreter.h"
 
+#include <functional>
+
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/split.hpp>
 
 #include "libbashWalker.h"
@@ -109,3 +112,36 @@ bool interpreter::call(const std::string& name,
 
   return true;
 }
+
+void interpreter::replace_all(std::string& value,
+                              const std::string& pattern,
+                              const std::string& replacement)
+{
+  boost::replace_all(value, pattern, replacement);
+}
+
+void interpreter::replace_at_end(std::string& value,
+                                 const std::string& pattern,
+                                 const std::string& replacement)
+{
+  if(value.size() >= pattern.size() &&
+     value.substr(value.size() - pattern.size()) == pattern)
+    value.replace(value.size() - pattern.size(),
+                  pattern.size(),
+                  replacement);
+}
+
+void interpreter::replace_at_start(std::string& value,
+                                   const std::string& pattern,
+                                   const std::string& replacement)
+{
+  if(value.substr(0, pattern.size()) == pattern)
+    value.replace(0, pattern.size(), replacement);
+}
+
+void interpreter::replace_first(std::string& value,
+                                const std::string& pattern,
+                                const std::string& replacement)
+{
+  boost::replace_first(value, pattern, replacement);
+}

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 22a083e..72b8e3b 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -563,6 +563,20 @@ public:
     return value.substr(offset, length);
   }
 
+  /// \brief perform replacement expansion
+  /// \param the name of the varaible that needs to be expanded
+  /// \param the function object used to perform expansion
+  /// \param array index, use index=0 if it's not an array
+  /// \return the expanded value
+  std::string do_replace_expansion(const std::string& name,
+                                   std::function<void(std::string&)> replacer,
+                                   const unsigned index) const
+  {
+    std::string value = resolve<std::string>(name, index);
+    replacer(value);
+    return value;
+  }
+
   /// \brief get the length of a string variable
   /// \param the name of the variable
   /// \return the length
@@ -600,5 +614,37 @@ public:
   /// \param the value of the word
   //. \param[out] the splitted result
   void split_word(const std::string& word, std::vector<std::string>& output);
+
+  /// \brief perform expansion like ${var//foo/bar}
+  /// \param the value to be expanded
+  /// \param the pattern used to match the value
+  /// \param the replacement string
+  static void replace_all(std::string& value,
+                          const std::string& pattern,
+                          const std::string& replacement);
+
+  /// \brief perform expansion like ${var/%foo/bar}
+  /// \param the value to be expanded
+  /// \param the pattern used to match the value
+  /// \param the replacement string
+  static void replace_at_end(std::string& value,
+                             const std::string& pattern,
+                             const std::string& replacement);
+
+  /// \brief perform expansion like ${var/#foo/bar}
+  /// \param the value to be expanded
+  /// \param the pattern used to match the value
+  /// \param the replacement string
+  static void replace_at_start(std::string& value,
+                               const std::string& pattern,
+                               const std::string& replacement);
+
+  /// \brief perform expansion like ${var/foo/bar}
+  /// \param the value to be expanded
+  /// \param the pattern used to match the value
+  /// \param the replacement string
+  static void replace_first(std::string& value,
+                            const std::string& pattern,
+                            const std::string& replacement);
 };
 #endif



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-20 14:04 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-20 14:04 UTC (permalink / raw
  To: gentoo-commits

commit:     3b3d66ad8eccbdafc155aa065e96d50fbf7fa050
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Wed Apr 20 09:10:03 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Apr 20 13:44:30 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=3b3d66ad

Walker: first support for command substitution

A simple command substitution is supported. Currently the commands
are executed within the current process.

---
 bashast/libbashWalker.g                 |   12 ++++++++++++
 scripts/command_execution.ebuild        |    2 ++
 scripts/command_execution.ebuild.result |    2 ++
 src/core/interpreter.cpp                |    6 ++++++
 src/core/interpreter.h                  |   13 +++++++++++++
 5 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 72fbf73..b6123d9 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -39,6 +39,7 @@ options
 @postinclude{
 
 	#include <iostream>
+	#include <sstream>
 
 	#include <boost/format.hpp>
 
@@ -144,6 +145,7 @@ string_expr returns[std::string libbash_value, bool quoted]
 				$libbash_value += boost::lexical_cast<std::string>(value); $quoted = false;
 			})
 		|(var_ref[false]) => libbash_string=var_ref[false] { $libbash_value += libbash_string; $quoted = false; }
+		|libbash_string=command_substitution { $libbash_value += libbash_string; $quoted = false; }
 		|(libbash_string=any_string { $libbash_value += libbash_string; $quoted = false; })
 	)+);
 
@@ -308,6 +310,16 @@ command_list: ^(LIST logic_command_list+);
 
 compound_command: ^(CURRENT_SHELL command_list);
 
+command_substitution returns[std::string libbash_value]
+@declarations {
+	std::stringstream out;
+}
+	:^(COMMAND_SUB{ walker->set_output_stream(&out); } command_list) {
+		walker->restore_output_stream();
+		$libbash_value = out.str();
+		walker->trim_trailing_eols($libbash_value);
+	};
+
 function_def returns[int placeholder]
 	:^(FUNCTION ^(STRING name) {
 		// Define the function with current index

diff --git a/scripts/command_execution.ebuild b/scripts/command_execution.ebuild
index d76c230..0f7cd03 100644
--- a/scripts/command_execution.ebuild
+++ b/scripts/command_execution.ebuild
@@ -6,3 +6,5 @@ hi
 echo hello world
 true
 false
+FOO001=$(echo hello)
+FOO002=$(hi)

diff --git a/scripts/command_execution.ebuild.result b/scripts/command_execution.ebuild.result
index 984ab54..4330a65 100644
--- a/scripts/command_execution.ebuild.result
+++ b/scripts/command_execution.ebuild.result
@@ -1,2 +1,4 @@
 Hello World
 hello world
+FOO001=hello
+FOO002=Hello World

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index a5a3307..f7e8f64 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -30,6 +30,7 @@
 #include <boost/algorithm/string/join.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/trim.hpp>
 
 #include "libbashWalker.h"
 
@@ -157,3 +158,8 @@ void interpreter::lazy_remove_at_end(std::string& value,
 {
   replace_at_end(value, pattern, "");
 }
+
+void interpreter::trim_trailing_eols(std::string& value)
+{
+  boost::trim_right_if(value, boost::is_any_of("\n"));
+}

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 0656299..af81c49 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -132,6 +132,16 @@ public:
     return members.end();
   }
 
+  void set_output_stream(std::ostream* stream)
+  {
+    out = stream;
+  }
+
+  void restore_output_stream()
+  {
+    out = &std::cout;
+  }
+
   /// \brief parse the text value of a tree to integer
   /// \param the target tree
   /// \return the parsed value
@@ -684,5 +694,8 @@ public:
   static void lazy_remove_at_end(std::string& value,
                                  const std::string& pattern);
 
+  /// \brief remove trailing EOLs from the value
+  /// \param[in, out] the target
+  static void trim_trailing_eols(std::string& value);
 };
 #endif



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-20 14:04 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-20 14:04 UTC (permalink / raw
  To: gentoo-commits

commit:     d0a9b80bc20ac38460c73f6b2e1c66c372a42cc1
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Mon Apr 18 14:44:11 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Apr 20 12:48:43 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=d0a9b80b

Walker: first support for function arguments

Local stack is added to support function arguments. Word splitting
will happen for function arguments. Function execution needs proper
preparation and cleanup so we move these logic into interpreter
class to keep our grammar clean.

---
 bashast/libbashWalker.g            |   77 ++++++++++++++++++++++--------------
 scripts/function_def.ebuild        |   18 ++++++++
 scripts/function_def.ebuild.result |    9 ++++
 src/core/interpreter.cpp           |   52 ++++++++++++++++++++++++
 src/core/interpreter.h             |   61 ++++++++++++++++++++--------
 5 files changed, 170 insertions(+), 47 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 76400f3..33db85c 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -29,6 +29,7 @@ options
 
 	#include <memory>
 	#include <string>
+	#include <vector>
 
 	class interpreter;
 	void set_interpreter(std::shared_ptr<interpreter> w);
@@ -37,9 +38,10 @@ options
 
 @postinclude{
 
-	#include "core/interpreter.h"
 	#include <boost/format.hpp>
 
+	#include "core/interpreter.h"
+
 }
 
 @members{
@@ -114,31 +116,39 @@ var_def
 	unsigned index = 0;
 	bool is_null = true;
 }
-	:^(EQUALS name (libbash_string=string_expr { is_null = false; })?) {
-		walker->set_value($name.libbash_value, libbash_string, $name.index, is_null);
+	:^(EQUALS name (string_expr { is_null = false; })?) {
+		walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index, is_null);
 	}
 	|^(EQUALS libbash_name=name_base ^(ARRAY (
-										(libbash_string=string_expr
+										(expr=string_expr
 										|^(EQUALS value=arithmetics {
 												set_index(libbash_name, index, value);
-											} libbash_string=string_expr))
-										{ values[index++] = libbash_string; })*
+											} expr=string_expr))
+										{ values[index++] = expr.libbash_value; })*
 									 )){
 		walker->define(libbash_name, values);
 	};
 
-string_expr returns[std::string libbash_value]
+string_expr returns[std::string libbash_value, bool quoted]
 	:^(STRING(
-		(DOUBLE_QUOTED_STRING) => ^(DOUBLE_QUOTED_STRING (libbash_string=double_quoted_string { $libbash_value += libbash_string; })*)
-		|(ARITHMETIC_EXPRESSION) => ^(ARITHMETIC_EXPRESSION value=arithmetics { $libbash_value = boost::lexical_cast<std::string>(value); })
-		|(var_ref[false]) => libbash_string=var_ref[false] { $libbash_value = libbash_string; }
-		|(libbash_string=any_string { $libbash_value += libbash_string; })+
+		(DOUBLE_QUOTED_STRING) =>
+			^(DOUBLE_QUOTED_STRING (libbash_string=double_quoted_string { $libbash_value += libbash_string; })*) {
+				$quoted = true;
+			}
+		|(ARITHMETIC_EXPRESSION) =>
+			^(ARITHMETIC_EXPRESSION value=arithmetics {
+				$libbash_value = boost::lexical_cast<std::string>(value); $quoted = false;
+			})
+		|(var_ref[false]) => libbash_string=var_ref[false] { $libbash_value = libbash_string; $quoted = false; }
+		|(libbash_string=any_string { $libbash_value += libbash_string; $quoted = false; })+
 	));
 
 //double quoted string rule, allows expansions
 double_quoted_string returns[std::string libbash_value]
 	:(var_ref[true]) => libbash_string=var_ref[true] { $libbash_value = libbash_string; }
-	|(ARITHMETIC_EXPRESSION) => ^(ARITHMETIC_EXPRESSION value=arithmetics) { $libbash_value = boost::lexical_cast<std::string>(value); }
+	|(ARITHMETIC_EXPRESSION) => ^(ARITHMETIC_EXPRESSION value=arithmetics) {
+		$libbash_value = boost::lexical_cast<std::string>(value);
+	}
 	|libbash_string=any_string { $libbash_value = libbash_string; };
 
 any_string returns[std::string libbash_value]
@@ -185,12 +195,17 @@ var_expansion returns[std::string libbash_value]
 
 word returns[std::string libbash_value]
 	:(num) => libbash_string=num { $libbash_value = libbash_string; }
-	|libbash_string=string_expr { $libbash_value = libbash_string; }
+	|string_expr { $libbash_value = $string_expr.libbash_value; }
 	|value=arithmetics { $libbash_value = boost::lexical_cast<std::string>(value); };
 
 //variable reference
 var_ref [bool double_quoted] returns[std::string libbash_value]
-	:^(VAR_REF name) { $libbash_value = walker->resolve<std::string>($name.libbash_value, $name.index); }
+	:^(VAR_REF name) {
+		$libbash_value = walker->resolve<std::string>($name.libbash_value, $name.index);
+	}
+	|^(VAR_REF libbash_string=num) {
+		$libbash_value = walker->resolve<std::string>(libbash_string);
+	}
 	|^(VAR_REF ^(libbash_string=name_base AT)) { walker->get_all_elements(libbash_string, $libbash_value); }
 	|^(VAR_REF ^(libbash_string=name_base TIMES)) {
 		if(double_quoted)
@@ -205,29 +220,31 @@ command
 	|simple_command;
 
 simple_command
-	:^(COMMAND libbash_string=string_expr argument* var_def*) {
-		ANTLR3_MARKER func_index;
-		if((func_index = walker->get_function_index(libbash_string)) != -1)
+@declarations {
+	std::vector<std::string> libbash_args;
+}
+	:^(COMMAND string_expr (argument[libbash_args])* var_def*) {
+		if(!walker->call($string_expr.libbash_value,
+						 libbash_args,
+						 ctx,
+						 compound_command))
+			throw interpreter_exception("Unimplemented command: " + $string_expr.libbash_value);
+	};
+
+argument[std::vector<std::string>& args]
+	: string_expr {
+		if($string_expr.quoted)
 		{
-			// Saving current index
-			ANTLR3_MARKER curr = INDEX();
-			// Push function index into INPUT
-			INPUT->push(INPUT, func_index);
-			// Execute function body
-			compound_command(ctx);
-			// Reset to the previous index
-			SEEK(curr);
+			args.push_back($string_expr.libbash_value);
 		}
 		else
 		{
-			throw interpreter_exception("Unimplemented command: " + libbash_string);
+			std::vector<std::string> arguments;
+			walker->split_word($string_expr.libbash_value, arguments);
+			args.insert(args.end(), arguments.begin(), arguments.end());
 		}
 	};
 
-argument
-	:var_ref[false]
-	|string_expr;
-
 logic_command_list
 	:command
 	|^(LOGICAND command command)

diff --git a/scripts/function_def.ebuild b/scripts/function_def.ebuild
index 8316c5f..194d030 100644
--- a/scripts/function_def.ebuild
+++ b/scripts/function_def.ebuild
@@ -8,3 +8,21 @@ src_unpack
 src_unpack
 
 MY_PV=2.0.3-r1
+
+nested_func_with_args() {
+	ARG6=$1
+	ARG7=$3
+}
+
+func_with_args() {
+	ARG1=$1
+	ARG2=$2
+	ARG3=$3
+	ARG4=$4
+	ARG5=$5
+	nested_func_with_args $4
+}
+FOO001="4		5"
+ARRAY=(1 2 3)
+func_with_args ${ARRAY[@]} $FOO001
+func_with_args 100 $ARG2 $ARG3 $ARG4

diff --git a/scripts/function_def.ebuild.result b/scripts/function_def.ebuild.result
index dbbc7eb..de9f3f8 100644
--- a/scripts/function_def.ebuild.result
+++ b/scripts/function_def.ebuild.result
@@ -1,2 +1,11 @@
+ARG1=100
+ARG2=2
+ARG3=3
+ARG4=4
+ARG5=
+ARG6=4
+ARG7=
+ARRAY=1 2 3
 EAPI=5
+FOO001=4		5
 MY_PV=2.0.3-r1

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index d9004e8..c683315 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -24,7 +24,11 @@
 
 #include "core/interpreter.h"
 
+#include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/split.hpp>
+
+#include "libbashWalker.h"
 
 void interpreter::get_all_elements_joined(const std::string& name,
                                           const std::string& delim,
@@ -57,3 +61,51 @@ void interpreter::get_all_elements_IFS_joined(const std::string& name,
                           resolve<std::string>("IFS").substr(0, 1),
                           result);
 }
+
+void interpreter::split_word(const std::string& word, std::vector<std::string>& output)
+{
+  const std::string& delimeter = resolve<std::string>("IFS");
+  boost::split(output, word, boost::is_any_of(delimeter), boost::token_compress_on);
+}
+
+inline void define_function_arguments(std::unique_ptr<scope>& current_stack,
+                                      const std::vector<std::string>& arguments)
+{
+  for(auto i = 0u; i != arguments.size(); ++i)
+  {
+    const std::string& name = boost::lexical_cast<std::string>(i + 1);
+    (*current_stack)[name] = std::shared_ptr<variable>(new variable(name, arguments[i]));
+  }
+}
+
+bool interpreter::call(const std::string& name,
+                       const std::vector<std::string>& arguments,
+                       plibbashWalker ctx,
+                       std::function<void(plibbashWalker)> f)
+{
+  ANTLR3_MARKER func_index;
+  auto iter = functions.find(name);
+  if(iter == functions.end())
+    return false;
+  func_index = iter->second;
+
+  // Prepare function stack and arguments
+  local_members.push(std::unique_ptr<scope>(new scope));
+  define_function_arguments(local_members.top(), arguments);
+
+  auto INPUT = ctx->pTreeParser->ctnstream;
+  auto ISTREAM = INPUT->tnstream->istream;
+  // Saving current index
+  ANTLR3_MARKER curr = ISTREAM->index(ISTREAM);
+  // Push function index into INPUT
+  INPUT->push(INPUT, func_index);
+  // Execute function body
+  f(ctx);
+  // Reset to the previous index
+  ISTREAM->seek(ISTREAM, curr);
+
+  // Clear function stack
+  local_members.pop();
+
+  return true;
+}

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 7c5acdb..22a083e 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -29,6 +29,7 @@
 
 #include <functional>
 #include <memory>
+#include <stack>
 #include <string>
 
 #include <antlr3basetree.h>
@@ -36,12 +37,15 @@
 #include "core/symbols.hpp"
 #include "libbashLexer.h"
 
+typedef std::unordered_map<std::string, std::shared_ptr<variable>> scope;
+struct libbashWalker_Ctx_struct;
+typedef struct libbashWalker_Ctx_struct * plibbashWalker;
+
 ///
 /// \class interpreter
 /// \brief implementation for bash interpreter
 ///
 class interpreter{
-  typedef std::unordered_map<std::string, std::shared_ptr<variable>> scope;
 
   /// \var private::members
   /// \brief global symbol table for variables
@@ -51,6 +55,11 @@ class interpreter{
   /// \brief global symbol table for functions
   std::unordered_map<std::string, ANTLR3_MARKER> functions;
 
+  /// \var private::local_members
+  /// \brief local scope for function arguments, execution environment and
+  ///        local variables
+  std::stack<std::unique_ptr<scope>> local_members;
+
   /// \brief calculate the correct offset when offset < 0 and check whether
   ///        the real offset is in legal range
   /// \param[in,out] a value/result argument referring to offset
@@ -376,7 +385,8 @@ public:
     return new_value;
   }
 
-  /// \brief resolve string/int variable
+  /// \brief resolve string/int variable, local scope will be
+  ///        checked first, then global scope
   /// \param variable name
   /// \param array index, use index=0 if it's not an array
   /// \return the value of the variable, call default constructor if
@@ -384,10 +394,17 @@ public:
   template <typename T>
   T resolve(const std::string& name, const unsigned index=0) const
   {
-    auto i = members.find(name);
-    if(i == members.end())
+    if(!local_members.empty())
+    {
+      auto iter_local = local_members.top()->find(name);
+      if(iter_local != local_members.top()->end())
+        return iter_local->second->get_value<T>(index);
+    }
+
+    auto iter_global = members.find(name);
+    if(iter_global == members.end())
       return T();
-    return i->second->get_value<T>(index);
+    return iter_global->second->get_value<T>(index);
   }
 
   /// \brief resolve array variable
@@ -444,7 +461,7 @@ public:
     return new_value;
   }
 
-  /// \brief define a new variable
+  /// \brief define a new global variable
   /// \param the name of the variable
   /// \param the value of the variable
   /// \param whether it's readonly, default is false
@@ -470,17 +487,16 @@ public:
     functions[name] = body_index;
   }
 
-  /// \brief get the index of the function in ANTLR3_COMMON_TREE_NODE_STREAM
-  /// \param the name of the function
-  /// \return the index of the function
-  ANTLR3_MARKER get_function_index(const std::string& name) const
-  {
-    auto iter = functions.find(name);
-    if(iter == functions.end())
-      return -1;
-    return iter->second;
-  }
-
+  /// \brief make function call
+  /// \param function name
+  /// \param function arguments
+  /// \param walker context
+  /// \param the function that needs to be executed
+  /// \return whether the execution is successful
+  bool call(const std::string& name,
+            const std::vector<std::string>& arguments,
+            plibbashWalker ctx,
+            std::function<void(plibbashWalker)> f);
 
   /// \brief perform ${parameter:−word} expansion
   /// \param the name of the parameter
@@ -570,8 +586,19 @@ public:
       return i->second->get_array_length();
   }
 
+  /// \brief get all array elements concatenated by space
+  /// \param the name of the array
+  /// \param[out] the concatenated string
   void get_all_elements(const std::string&, std::string&) const;
 
+  /// \brief get all array elements concatenated by the first character of IFS
+  /// \param the name of the array
+  /// \param[out] the concatenated string
   void get_all_elements_IFS_joined(const std::string&, std::string&) const;
+
+  /// \brief implementation of word splitting
+  /// \param the value of the word
+  //. \param[out] the splitted result
+  void split_word(const std::string& word, std::vector<std::string>& output);
 };
 #endif



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-06 15:07 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-06 15:07 UTC (permalink / raw
  To: gentoo-commits

commit:     3c91e9d0018e0763dff71c856bd9c0c3fd4b83aa
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Wed Apr  6 10:25:29 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Apr  6 10:25:29 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=3c91e9d0

Implement ${#parameter} expansion

---
 bashast/libbashWalker.g             |    3 +++
 scripts/var_expansion.ebuild        |    2 ++
 scripts/var_expansion.ebuild.result |    2 ++
 src/core/interpreter.h              |    8 ++++++++
 4 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index e6f4393..71aba2e 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -104,6 +104,9 @@ var_expansion returns[std::string libbash_value]
 			libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset, length);
 		else
 			libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset);
+	}
+	|^(POUND var_name) {
+		libbash_value = boost::lexical_cast<std::string>(walker->get_length($var_name.libbash_value));
 	};
 
 word returns[std::string libbash_value]:

diff --git a/scripts/var_expansion.ebuild b/scripts/var_expansion.ebuild
index b0402a8..0045b5e 100644
--- a/scripts/var_expansion.ebuild
+++ b/scripts/var_expansion.ebuild
@@ -22,3 +22,5 @@ FOO020=${FOO009: -2:2}
 FOO021=${FOO009:2:100}
 FOO022=${FOO009: -2:100}
 FOO023=${NOT_EXIST:0:2}
+FOO024=${#FOO009}
+FOO025=${#NOT_EXIST}

diff --git a/scripts/var_expansion.ebuild.result b/scripts/var_expansion.ebuild.result
index 5695d1a..e7b767a 100644
--- a/scripts/var_expansion.ebuild.result
+++ b/scripts/var_expansion.ebuild.result
@@ -23,3 +23,5 @@ FOO020=lo
 FOO021=llo
 FOO022=lo
 FOO023=
+FOO024=5
+FOO025=0

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index cde08ac..1e5f1dc 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -485,5 +485,13 @@ public:
     return value.substr(offset, length);
   }
 
+  /// \brief get the length of a string variable
+  /// \param the name of the variable
+  /// \return the length
+  int get_length(const std::string& name)
+  {
+    return resolve<std::string>(name).size();
+  }
+
 };
 #endif



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-06  7:43 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-06  7:43 UTC (permalink / raw
  To: gentoo-commits

commit:     cc66a932c3756730ddf11198999c39a4f6f9a9e1
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Tue Apr  5 12:02:24 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Tue Apr  5 13:49:13 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=cc66a932

Implement ${param:=w} and ${param:+w} expansion

---
 bashast/libbashWalker.g             |    6 ++++++
 scripts/var_expansion.ebuild        |    4 ++++
 scripts/var_expansion.ebuild.result |    5 +++++
 src/core/interpreter.h              |   20 ++++++++++++++++++++
 4 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index a25c58c..ad8e444 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -89,6 +89,12 @@ var_name returns[std::string libbash_value]
 var_expansion returns[std::string libbash_value]:
 	^(USE_DEFAULT var_name libbash_word=word) {
 		libbash_value = walker->do_default_expansion($var_name.libbash_value, libbash_word);
+	}
+	|^(ASSIGN_DEFAULT var_name libbash_word=word) {
+		libbash_value = walker->do_assign_expansion($var_name.libbash_value, libbash_word);
+	}
+	|^(USE_ALTERNATE var_name libbash_word=word) {
+		libbash_value = walker->do_alternate_expansion($var_name.libbash_value, libbash_word);
 	};
 
 word returns[std::string libbash_value]:

diff --git a/scripts/var_expansion.ebuild b/scripts/var_expansion.ebuild
index 533e7a7..f0ad504 100644
--- a/scripts/var_expansion.ebuild
+++ b/scripts/var_expansion.ebuild
@@ -5,3 +5,7 @@ FOO2="${EAPI3:-hello}"
 FOO3=123
 FOO4=$EAPI
 FOO5=$(( 1+1 ))
+FOO6=${EAPI:=hello}
+FOO7=${FOO8:=hello}
+FOO9=${EAPI:+hello}
+FOO10=${NOT_EXIST:+hello}

diff --git a/scripts/var_expansion.ebuild.result b/scripts/var_expansion.ebuild.result
index bad2cf3..7d2e5ca 100644
--- a/scripts/var_expansion.ebuild.result
+++ b/scripts/var_expansion.ebuild.result
@@ -1,7 +1,12 @@
 EAPI=3
 EAPI4=4
 FOO=3
+FOO10=
 FOO2=hello
 FOO3=123
 FOO4=3
 FOO5=2
+FOO6=3
+FOO7=hello
+FOO8=hello
+FOO9=hello

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index ab6b9e8..aad8f48 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -424,5 +424,25 @@ public:
   {
     return (is_unset_or_null(name)? value : resolve<std::string>(name));
   }
+
+  /// \brief perform ${parameter:=word} expansion
+  /// \param the name of the parameter
+  /// \param the value of the word
+  /// \return the expansion result
+  const std::string do_assign_expansion(const std::string& name,
+                                        const std::string& value)
+  {
+    return (is_unset_or_null(name)? set_value(name, value) : resolve<std::string>(name));
+  }
+
+  /// \brief perform ${parameter:+word} expansion
+  /// \param the name of the parameter
+  /// \param the value of the word
+  /// \return the expansion result
+  const std::string do_alternate_expansion(const std::string& name,
+                                           const std::string& value)
+  {
+    return (is_unset_or_null(name)? "" : value);
+  }
 };
 #endif



^ permalink raw reply related	[flat|nested] 14+ messages in thread
* [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
@ 2011-04-04 16:09 Petteri Räty
  0 siblings, 0 replies; 14+ messages in thread
From: Petteri Räty @ 2011-04-04 16:09 UTC (permalink / raw
  To: gentoo-commits

commit:     e399dff749def2cd11ab44cf53896c849f1429a8
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Mon Apr  4 08:57:46 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Mon Apr  4 15:57:05 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=e399dff7

Implement parameter expansion: ${parameter:-word}

---
 bashast/libbashWalker.g             |   26 ++++++++++++++++++++++++--
 scripts/var_expansion.ebuild        |    2 ++
 scripts/var_expansion.ebuild.result |    2 ++
 src/core/interpreter.h              |    6 ++++++
 4 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index ddfef7a..d0f89bf 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -62,7 +62,8 @@ var_def:
 
 string_expr	returns[std::string libbash_value]:
 	^(STRING libbash_string=string_expr) { $libbash_value = libbash_string; }
-	|^(DOUBLE_QUOTED_STRING (libbash_string=dqstr { $libbash_value += libbash_string; })*);
+	|^(DOUBLE_QUOTED_STRING (libbash_string=dqstr { $libbash_value += libbash_string; })*)
+	|^(STRING libbash_string=dqstr) { $libbash_value = libbash_string; };
 
 //A rule for filenames/strings
 res_word_str returns[std::string libbash_value]
@@ -109,9 +110,30 @@ dqstr returns[std::string libbash_value]:
 	| libbash_string=var_ref { $libbash_value = libbash_string; }
 	| ^(ARITHMETIC_EXPRESSION value=arithmetics) { $libbash_value = boost::lexical_cast<std::string>(value); };
 
+//Allowable variable names in the variable expansion
+var_name returns[std::string libbash_value]
+@after {
+	$libbash_value = walker->get_string($var_name.start);
+}:
+	num|name|TIMES|AT;
+
+var_exp returns[std::string libbash_value]:
+	^(USE_DEFAULT var_name libbash_word=word) {
+		libbash_value = walker->do_default_expansion($var_name.libbash_value, libbash_word);
+	};
+
+word returns[std::string libbash_value]:
+	// Avoid conflict with arithmetics (both have VAR_DEF)
+	(var_ref) => libbash_string=var_ref { $libbash_value = libbash_string; }
+	// Avoid conflict with arithmetics (both have num)
+	|(num) => libbash_string=num { $libbash_value = libbash_string; }
+	|libbash_string=string_expr { $libbash_value = libbash_string; }
+	|value=arithmetics { $libbash_value = boost::lexical_cast<std::string>(value); };
+
 //variable reference
 var_ref returns[std::string libbash_value]:
-	^(VAR_REF libbash_name=name) { $libbash_value=walker->resolve<std::string>(libbash_name); };
+	^(VAR_REF libbash_name=name) { $libbash_value = walker->resolve<std::string>(libbash_name); }
+	|^(VAR_REF libbash_string=var_exp) { $libbash_value = libbash_string; };
 
 // shell arithmetic
 arithmetics returns[int value]

diff --git a/scripts/var_expansion.ebuild b/scripts/var_expansion.ebuild
index a5cadb6..62e95c3 100644
--- a/scripts/var_expansion.ebuild
+++ b/scripts/var_expansion.ebuild
@@ -1,2 +1,4 @@
 EAPI="3"
 EAPI4="$(($EAPI+1))"
+FOO="${EAPI:-hello}"
+FOO2="${EAPI3:-hello}"

diff --git a/scripts/var_expansion.ebuild.result b/scripts/var_expansion.ebuild.result
index cec88e4..f92abe4 100644
--- a/scripts/var_expansion.ebuild.result
+++ b/scripts/var_expansion.ebuild.result
@@ -1,2 +1,4 @@
 EAPI=3
 EAPI4=4
+FOO=3
+FOO2=hello

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 1ce1076..2fc8703 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -410,5 +410,11 @@ public:
         new variable(name, value, readonly, is_null));
     members.define(target);
   }
+
+  const std::string do_default_expansion(const std::string& name,
+                                         const std::string& value)
+  {
+    return (is_null(name)? value : resolve<std::string>(name));
+  }
 };
 #endif



^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-08-19 14:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-14  4:50 [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/ Petteri Räty
  -- strict thread matches above, loose matches on Subject: below --
2012-08-19 14:54 Petteri Räty
2011-08-04 13:53 Petteri Räty
2011-06-09  8:15 Petteri Räty
2011-06-03 14:48 Petteri Räty
2011-05-15 11:19 Petteri Räty
2011-05-11  7:19 Petteri Räty
2011-05-07 12:25 Petteri Räty
2011-04-20 14:04 Petteri Räty
2011-04-20 14:04 Petteri Räty
2011-04-20 14:04 Petteri Räty
2011-04-06 15:07 Petteri Räty
2011-04-06  7:43 Petteri Räty
2011-04-04 16:09 Petteri Räty

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox