From f4bdbb24bdbcb12655005202dec2fc6e216f0ed3 Mon Sep 17 00:00:00 2001 From: Mu Qiao Date: Thu, 23 Feb 2012 15:58:27 +0800 Subject: Parser&Walker: respect precedence in builtin test Builtin test does not support shortcut capability. Tests are added to verify that. --- bashast/bashast.g | 28 +++++++++++++++++++++------- bashast/gunit/cond_main.gunit | 5 +++-- bashast/libbashWalker.g | 13 +++++-------- scripts/test_expr.bash | 8 ++++++++ 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/bashast/bashast.g b/bashast/bashast.g index b383219..8286a00 100644 --- a/bashast/bashast.g +++ b/bashast/bashast.g @@ -126,7 +126,8 @@ tokens{ NOT_EQUALS; EQUALS_TO; - BUILTIN_LOGIC; + BUILTIN_LOGIC_AND; + BUILTIN_LOGIC_OR; FUNCTION; } @@ -651,13 +652,16 @@ keyword_binary_string_operator | BLANK!? LESS_THAN BLANK!? | BLANK!? GREATER_THAN BLANK!?; + +builtin_condition_and + : builtin_condition_primary (builtin_logic_and^ BLANK! builtin_condition_primary)?; builtin_condition - : ((BANG) => builtin_negation_primary|builtin_keyword_condition_primary) - (BLANK! builtin_logic_operator^ BLANK! builtin_condition)?; + : builtin_condition_and (builtin_logic_or^ BLANK! builtin_condition_and)?; builtin_negation_primary - : BANG BLANK builtin_keyword_condition_primary -> ^(NEGATION builtin_keyword_condition_primary); -builtin_keyword_condition_primary + : BANG BLANK builtin_condition_primary -> ^(NEGATION builtin_condition_primary); +builtin_condition_primary : LPAREN! BLANK!? builtin_condition BLANK!? RPAREN! + | (BANG) => builtin_negation_primary | (unary_operator) => builtin_condition_unary | builtin_condition_binary; builtin_condition_unary @@ -671,8 +675,18 @@ builtin_binary_string_operator | BANG EQUALS -> NOT_EQUALS | ESC_LT | ESC_GT; -builtin_logic_operator - : unary_operator -> ^(BUILTIN_LOGIC unary_operator); +builtin_logic_and +#ifdef OUTPUT_C + : {LA(1) == BLANK && LA(2) == MINUS && LA(3) == LETTER && "a" == get_string(LT(3))}?=> BLANK MINUS LETTER -> BUILTIN_LOGIC_AND; +#else + : {LA(1) == BLANK && LA(2) == MINUS && LA(3) == LETTER && "a".equals(get_string(LT(3)))}?=> BLANK MINUS LETTER -> BUILTIN_LOGIC_AND; +#endif +builtin_logic_or +#ifdef OUTPUT_C + : {LA(1) == BLANK && LA(2) == MINUS && LA(3) == LETTER && "o" == get_string(LT(3))}?=> BLANK MINUS LETTER -> BUILTIN_LOGIC_OR; +#else + : {LA(1) == BLANK && LA(2) == MINUS && LA(3) == LETTER && "o".equals(get_string(LT(3)))}?=> BLANK MINUS LETTER -> BUILTIN_LOGIC_OR; +#endif binary_operator : MINUS! NAME^; diff --git a/bashast/gunit/cond_main.gunit b/bashast/gunit/cond_main.gunit index 5ecd024..bf86d7d 100644 --- a/bashast/gunit/cond_main.gunit +++ b/bashast/gunit/cond_main.gunit @@ -31,8 +31,9 @@ condition_expr: "[ a == b ]" -> (BUILTIN_TEST (= (STRING a) (STRING b))) "[ a != b ]" -> (BUILTIN_TEST (NOT_EQUALS (STRING a) (STRING b))) "[[ \"${DISTUTILS_SRC_TEST}\" =~ ^(setup\.py|nosetests|py\.test|trial(\ .*)?)$ ]]" -> (KEYWORD_TEST (MATCH_REGULAR_EXPRESSION (STRING (DOUBLE_QUOTED_STRING (VAR_REF DISTUTILS_SRC_TEST))) (STRING ^ ( setup \ . py | nosetests | py \ . test | trial ( \ . * ) ? ) $))) -"[ -n \"$FROM_LANG\" -a -n \"$TO_LANG\" ]" -> (BUILTIN_TEST (BUILTIN_LOGIC a (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF FROM_LANG)))) (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF TO_LANG)))))) -"[ -n \"$FROM_LANG\" -o -n \"$TO_LANG\" ]" -> (BUILTIN_TEST (BUILTIN_LOGIC o (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF FROM_LANG)))) (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF TO_LANG)))))) +"[ -n \"$FROM_LANG\" -a -n \"$TO_LANG\" ]" -> (BUILTIN_TEST (BUILTIN_LOGIC_AND (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF FROM_LANG)))) (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF TO_LANG)))))) +"[ -n \"$FROM_LANG\" -o -n \"$TO_LANG\" ]" -> (BUILTIN_TEST (BUILTIN_LOGIC_OR (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF FROM_LANG)))) (n (STRING (DOUBLE_QUOTED_STRING (VAR_REF TO_LANG)))))) +"[ -n \"a\" -o -n \"a\" -a -n \"a\" ]" -> (BUILTIN_TEST (BUILTIN_LOGIC_OR (n (STRING (DOUBLE_QUOTED_STRING a))) (BUILTIN_LOGIC_AND (n (STRING (DOUBLE_QUOTED_STRING a))) (n (STRING (DOUBLE_QUOTED_STRING a)))))) "[[ \"${element}\" =~ (^[^[:space:]]+\ .) ]]" -> (KEYWORD_TEST (MATCH_REGULAR_EXPRESSION (STRING (DOUBLE_QUOTED_STRING (VAR_REF element))) (STRING ( ^ [ ^ [ : space : ] ] + \ . )))) "[[ a (KEYWORD_TEST (< (STRING a) (STRING b))) "[[ a>b ]]" -> (KEYWORD_TEST (> (STRING a) (STRING b))) diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g index e357642..7c7afaf 100644 --- a/bashast/libbashWalker.g +++ b/bashast/libbashWalker.g @@ -786,14 +786,11 @@ keyword_condition returns[bool status] builtin_condition returns[bool status] :^(NEGATION l=builtin_condition) { $status = !l; } - |^(BUILTIN_LOGIC o=LETTER l=builtin_condition r=builtin_condition) { - char op = get_char(o); - if(op == 'a') - $status = l && r; - else if(op == 'o') - $status = l || r; - else - throw libbash::parse_exception(std::string("unrecognized operator in built-in test: ") + op); + |^(BUILTIN_LOGIC_AND l=builtin_condition r=builtin_condition) { + $status = l && r; + } + |^(BUILTIN_LOGIC_OR l=builtin_condition r=builtin_condition) { + $status = l || r; } |s=builtin_condition_primary { $status = s; }; diff --git a/scripts/test_expr.bash b/scripts/test_expr.bash index 6ae7246..f8e7c03 100644 --- a/scripts/test_expr.bash +++ b/scripts/test_expr.bash @@ -61,3 +61,11 @@ i=1 [[ a == b && $((i=1)) ]] || echo $i # i should still be 0 i=1 [[ a == a && $((i=0)) ]] && echo $i # i should still be 0 +[ -n "a" -o -n "" -a -n "" ] && echo true +# builtin test doesn't support shortcut +i=1 +[ 1 -eq 2 -o $((i=0)) ] && echo $i # i should be 0 now +[ 1 -eq 1 -o $((i=1)) ] && echo $i # i should still be 1 +[ 1 -eq 2 -a $((i=1)) ] || echo $i # i should still be 1 +i=1 +[ 1 -eq 1 -a $((i=0)) ] && echo $i # i should still be 0 -- cgit v1.2.3-65-gdbad