diff options
author | Mu Qiao <qiaomuf@gentoo.org> | 2011-07-05 11:46:01 +0800 |
---|---|---|
committer | Mu Qiao <qiaomuf@gentoo.org> | 2011-07-06 16:02:03 +0800 |
commit | 75705b99bb90701616cb0c100a8703e21710f897 (patch) | |
tree | 230343b6154ea442a74ae58810ba711e064a6e37 /src | |
parent | Merge branch 'multithreading' (diff) | |
download | libbash-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.cpp | 21 | ||||
-rw-r--r-- | src/core/interpreter.h | 5 | ||||
-rw-r--r-- | src/core/tests/interpreter_test.cpp | 24 |
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)); +} |