aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-07-05 11:46:01 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-07-06 16:02:03 +0800
commit75705b99bb90701616cb0c100a8703e21710f897 (patch)
tree230343b6154ea442a74ae58810ba711e064a6e37 /src
parentMerge branch 'multithreading' (diff)
downloadlibbash-75705b99bb90701616cb0c100a8703e21710f897.tar.gz
libbash-75705b99bb90701616cb0c100a8703e21710f897.tar.bz2
libbash-75705b99bb90701616cb0c100a8703e21710f897.zip
Parser: reduce backtracking for command_atom
Backtracking is reduced by left refactoring function definition and bash command.
Diffstat (limited to 'src')
-rw-r--r--src/core/interpreter.cpp21
-rw-r--r--src/core/interpreter.h5
-rw-r--r--src/core/tests/interpreter_test.cpp24
3 files changed, 46 insertions, 4 deletions
diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index ba69143..539b9f1 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -310,6 +310,27 @@ void interpreter::define_function_arguments(scope& current_stack,
current_stack["*"].reset(new variable("*", positional_args, true));
}
+namespace
+{
+ bool check_function_name(const std::string& name)
+ {
+ using namespace boost::xpressive;
+ sregex bash_name_pattern =
+ !digit >>
+ ~(set[range('0', '9') | (set= '$', '\'', '"', '(', ')', ' ', '\n', '\r')]) >>
+ *(~(set= '$', '\'', '"', '(', ')', ' ', '\n', '\r'));
+ return regex_match(name, bash_name_pattern);
+ }
+}
+
+void interpreter::define_function(const std::string& name,
+ ANTLR3_MARKER body_index)
+{
+ if(!check_function_name(name))
+ throw libbash::parse_exception("illegal function name: " + name);
+ functions.insert(make_pair(name, function(*ast_stack.top(), body_index)));
+}
+
void interpreter::call(const std::string& name,
const std::vector<std::string>& arguments)
{
diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 3363ae7..801e24f 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -311,10 +311,7 @@ public:
/// \param name the name of the function
/// \param body_index the body index of the function
void define_function(const std::string& name,
- ANTLR3_MARKER body_index)
- {
- functions.insert(make_pair(name, function(*ast_stack.top(), body_index)));
- }
+ ANTLR3_MARKER body_index);
/// \brief push current AST, used for function definition
/// \param ast the pointer to the current ast
diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpreter_test.cpp
index d20697b..ecbcfd9 100644
--- a/src/core/tests/interpreter_test.cpp
+++ b/src/core/tests/interpreter_test.cpp
@@ -261,3 +261,27 @@ TEST(interpreter, undefined_function)
EXPECT_THROW(walker.call("undefined", {}), libbash::runtime_exception);
}
+
+TEST(interpreter, illegal_function_names)
+{
+ interpreter walker;
+ walker.push_current_ast(0);
+ EXPECT_THROW(walker.define_function("aa'bb", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa\"", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("333", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa$aa", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa(aa", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa)aa", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa aa", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa\naa", 0), libbash::parse_exception);
+ EXPECT_THROW(walker.define_function("aa\raa", 0), libbash::parse_exception);
+}
+
+TEST(interpreter, legal_function_names)
+{
+ interpreter walker;
+ walker.push_current_ast(0);
+ EXPECT_NO_THROW(walker.define_function("aabb", 0));
+ EXPECT_NO_THROW(walker.define_function("1abb", 0));
+ EXPECT_NO_THROW(walker.define_function("a-b", 0));
+}