diff --git a/src/parse.y b/src/parse.y index c1f6ddd96e..6cafa94021 100644 --- a/src/parse.y +++ b/src/parse.y @@ -456,17 +456,24 @@ expr: | '[' expr_list ']' { - // A little crufty: we peek at the type of - // the first expression in the list. If it's - // a record or a field assignment, then this - // is a record constructor. If not, then this - // is a list used for an initializer. - set_location(@1, @3); - Expr* e0 = $2->Exprs()[0]; - if ( e0->Tag() == EXPR_FIELD_ASSIGN || - e0->Type()->Tag() == TYPE_RECORD ) + bool is_record_ctor = true; + + // If every expression in the list is a field assignment, + // then treat it as a record constructor, else as a list + // used for an initializer. + + for ( int i = 0; i < $2->Exprs().length(); ++i ) + { + if ( $2->Exprs()[i]->Tag() != EXPR_FIELD_ASSIGN ) + { + is_record_ctor = false; + break; + } + } + + if ( is_record_ctor ) $$ = new RecordConstructorExpr($2); else $$ = $2; diff --git a/testing/btest/Baseline/language.table/out b/testing/btest/Baseline/language.table/out index 514cb6b02d..0d746ded2b 100644 --- a/testing/btest/Baseline/language.table/out +++ b/testing/btest/Baseline/language.table/out @@ -12,6 +12,7 @@ cardinality (PASS) cardinality (PASS) cardinality (PASS) cardinality (PASS) +cardinality (PASS) iterate over table (PASS) iterate over table (PASS) iterate over table (PASS) @@ -30,6 +31,11 @@ add element (PASS) in operator (PASS) add element (PASS) in operator (PASS) +composite index add element (PASS) +composite index in operator (PASS) +composite index in operator (PASS) +remove element (PASS) +!in operator (PASS) remove element (PASS) !in operator (PASS) remove element (PASS) diff --git a/testing/btest/language/table.bro b/testing/btest/language/table.bro index d1b0751970..3c8e8db280 100644 --- a/testing/btest/language/table.bro +++ b/testing/btest/language/table.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: bro -b %INPUT >out # @TEST-EXEC: btest-diff out function test_case(msg: string, expect: bool) @@ -26,6 +26,9 @@ event bro_init() local t10: table[port, string, bool] of string = { [10/udp, "curly", F] = "first", [11/udp, "braces", T] = "second" }; + local t11: table[conn_id, bool] of count = { + [ [$orig_h=1.1.1.1, $orig_p=1234/tcp, + $resp_h=2.2.2.2, $resp_p=4321/tcp], T ] = 42 }; # Type inference tests @@ -45,6 +48,7 @@ event bro_init() test_case( "cardinality", |t8| == 0 ); test_case( "cardinality", |t9| == 1 ); test_case( "cardinality", |t10| == 2 ); + test_case( "cardinality", |t11| == 1 ); test_case( "cardinality", |tg1| == 3 ); # Test iterating over each table @@ -121,6 +125,13 @@ event bro_init() test_case( "add element", |t5| == 3 ); test_case( "in operator", 10 in t5 ); + local cid = [$orig_h=1.1.1.1, $orig_p=1234/tcp, + $resp_h=2.2.2.2, $resp_p=4321/tcp]; + t11[[$orig_h=[::1], $orig_p=3/tcp, $resp_h=[::2], $resp_p=3/tcp], F] = 3; + test_case( "composite index add element", |t11| == 2 ); + test_case( "composite index in operator", [cid, T] in t11 ); + test_case( "composite index in operator", [[$orig_h=[::1], $orig_p=3/tcp, $resp_h=[::2], $resp_p=3/tcp], F] in t11 ); + # Test removing elements from each table (Note: cannot remove elements # from tables of multiple types) @@ -145,5 +156,8 @@ event bro_init() test_case( "remove element", |t5| == 2 ); test_case( "!in operator", 1 !in t5 ); + delete t11[cid, T]; + test_case( "remove element", |t11| == 1 ); + test_case( "!in operator", [cid, T] !in t11 ); }