#include #include using namespace lw; class SRDParserConfigTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( SRDParserConfigTest ); CPPUNIT_TEST( testWordIndex ); CPPUNIT_TEST( testRuleSimple ); CPPUNIT_TEST( testRuleABStarABB ); CPPUNIT_TEST( testMergedRules ); CPPUNIT_TEST( testRulesMultiContexts ); CPPUNIT_TEST( testContextIDs ); CPPUNIT_TEST( testEnumIDs ); CPPUNIT_TEST( testUnusedEnums ); CPPUNIT_TEST( testUnusedContexts ); CPPUNIT_TEST( testContextInheritance ); CPPUNIT_TEST( testErrorMissingCtxRule ); CPPUNIT_TEST( testErrorMissingCtxParent ); CPPUNIT_TEST( testErrorMissingEnum ); CPPUNIT_TEST( testErrorEmptyContext ); CPPUNIT_TEST( testErrorEmptyRule ); CPPUNIT_TEST( testErrorEmptyAlt ); CPPUNIT_TEST( testErrorEmptyRepeat ); CPPUNIT_TEST( testErrorRecursiveInheritance ); CPPUNIT_TEST( testErrorAmbiguousRules ); CPPUNIT_TEST( testErrorUBRSimpleOK ); CPPUNIT_TEST( testErrorUBRSimpleUnbalancedStart ); CPPUNIT_TEST( testErrorUBRSimpleUnbalancedEnd ); CPPUNIT_TEST( testErrorUBRAltsOKContained ); CPPUNIT_TEST( testErrorUBRAltsOKBalancing ); CPPUNIT_TEST( testErrorUBRAltsDifferent ); CPPUNIT_TEST( testErrorUBRAltsUnbalanced ); CPPUNIT_TEST( testErrorUBRRepsOK ); CPPUNIT_TEST( testErrorUBRRepsUnbalanced ); CPPUNIT_TEST( testTransition ); CPPUNIT_TEST_SUITE_END( ); void checkMergedRules( T_SRDParserConfig const& c ); public: void testWordIndex( ); void testRuleSimple( ); void testRuleABStarABB( ); void testMergedRules( ); void testRulesMultiContexts( ); void testContextIDs( ); void testEnumIDs( ); void testUnusedEnums( ); void testUnusedContexts( ); void testContextInheritance( ); void testErrorMissingCtxRule( ); void testErrorMissingCtxParent( ); void testErrorMissingEnum( ); void testErrorEmptyContext( ); void testErrorEmptyRule( ); void testErrorEmptyAlt( ); void testErrorEmptyRepeat( ); void testErrorRecursiveInheritance( ); void testErrorAmbiguousRules( ); void testErrorUBRSimpleOK( ); void testErrorUBRSimpleUnbalancedStart( ); void testErrorUBRSimpleUnbalancedEnd( ); void testErrorUBRAltsOKContained( ); void testErrorUBRAltsOKBalancing( ); void testErrorUBRAltsDifferent( ); void testErrorUBRAltsUnbalanced( ); void testErrorUBRRepsOK( ); void testErrorUBRRepsUnbalanced( ); void testTransition( ); }; CPPUNIT_TEST_SUITE_REGISTRATION( SRDParserConfigTest ); /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::checkMergedRules( T_SRDParserConfig const& c ) { CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.startStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.startStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 8 ) , c.endStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.endStates[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 2 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 3 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.endStates[ 4 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.endStates[ 5 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.endStates[ 6 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.endStates[ 7 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 8 ) , c.transitions.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 0 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.sizeOf( 1 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 2 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 3 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 4 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.transitions.sizeOf( 5 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 6 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.transitions.sizeOf( 7 ) ); // 0: "a" -> 1 { auto const& t( c.transitions.get( 0 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } // 1: "a" -> 2 { auto const& t( c.transitions.get( 1 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , t.next ); } // 1: "b" -> 3 { auto const& t( c.transitions.get( 1 , 1 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , t.next ); } // 2: "a" -> 4 { auto const& t( c.transitions.get( 2 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , t.next ); } // 3: "a" -> 5 { auto const& t( c.transitions.get( 3 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 5 ) , t.next ); } // 4: "a" -> 6 { auto const& t( c.transitions.get( 4 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 6 ) , t.next ); } // 6: "a" -> 7 { auto const& t( c.transitions.get( 6 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 7 ) , t.next ); } } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testWordIndex( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "test" << "and" << "test" ); d.context( T_String( "unused" ) ) << ( Rule( ) << "not" << "in" << "the" << "index" ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.words.size( ) ); CPPUNIT_ASSERT( c.words[ 0 ] == T_String( "test" ) ); CPPUNIT_ASSERT( c.words[ 1 ] == T_String( "and" ) ); } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testRuleSimple( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "test" ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.contexts.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.startStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.startStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.endStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.endStates[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 0 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.transitions.sizeOf( 1 ) ); auto const& t( c.transitions.get( 0 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } void SRDParserConfigTest::testRuleABStarABB( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << ( AtLeast( 0 ) << ( Alt( ) << "a" << "b" ) ) << "a" << "b" << "b" ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.contexts.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.startStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.startStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , c.endStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 2 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.endStates[ 3 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , c.transitions.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.sizeOf( 0 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.sizeOf( 1 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.sizeOf( 2 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.sizeOf( 3 ) ); // 0: "a" -> 1 { auto const& t( c.transitions.get( 0 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } // 0: "b" -> 0 { auto const& t( c.transitions.get( 0 , 1 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.next ); } // 1: "a" -> 1 { auto const& t( c.transitions.get( 1 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } // 1: "b" -> 2 { auto const& t( c.transitions.get( 1 , 1 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , t.next ); } // 2: "a" -> 1 { auto const& t( c.transitions.get( 2 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } // 2: "b" -> 3 { auto const& t( c.transitions.get( 2 , 1 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , t.next ); } // 3: "a" -> 1 { auto const& t( c.transitions.get( 3 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } // 3: "b" -> 0 { auto const& t( c.transitions.get( 3 , 1 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.next ); } } void SRDParserConfigTest::testMergedRules( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "a" ) << ( Rule( ) << "a" << "b" << "a" ) << ( Rule( ) << ( Between( 3 , 5 ) << "a" ) ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.contexts.size( ) ); checkMergedRules( c ); } void SRDParserConfigTest::testRulesMultiContexts( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "test" << EnterContext( "other" ) ); d.context( T_String( "other" ) ) << ( Rule( ) << "test" ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.contexts.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.startStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.startStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.startStates[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , c.endStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.endStates[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 2 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.endStates[ 3 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , c.transitions.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 0 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.transitions.sizeOf( 1 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 2 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.transitions.sizeOf( 3 ) ); { auto const& t( c.transitions.get( 0 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } { auto const& t( c.transitions.get( 2 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::WORD == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , t.next ); } } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testContextIDs( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "test" << EnterContext( "other" ) ) << ( Rule( ) << "test" << "number" << "two" << EnterContext( "other" ) ) << ( Rule( ) << "yet" << "another" << "test" << EnterContext( "other" ) ) << ( Rule( ) << "moar" << EnterContext( "moar" ) ) ; d.context( T_String( "other" ) ) << ( Rule( ) << "test" ); d.context( T_String( "moar" ) ) << ( Rule( ) << "test" ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , c.ruleContexts.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , c.ruleContexts.sizeOf( 0 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.ruleContexts.sizeOf( 1 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.ruleContexts.sizeOf( 2 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.ruleContexts[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.ruleContexts[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.ruleContexts[ 2 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.ruleContexts[ 3 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.ruleContexts[ 4 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.ruleContexts[ 5 ] ); } void SRDParserConfigTest::testEnumIDs( ) { T_String n( T_String::Pooled( "test" ) ); T_SRDParserDefs d( n ); { using namespace SRD; d.enumeration( n ) << "a" << "b"; d.context( n ) << ( Rule( ) << Enum( "test" ) ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.enums.size( ) ); CPPUNIT_ASSERT( c.enums[ 0 ].name( ) == n ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.contexts.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.startStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.startStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.endStates.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( T_SRDParserConfig::INVALID_END ) , c.endStates[ 0 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.endStates[ 1 ] ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , c.transitions.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.transitions.sizeOf( 0 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.transitions.sizeOf( 1 ) ); auto const& t( c.transitions.get( 0 , 0 ) ); CPPUNIT_ASSERT( E_SRDTransitionType::ENUM == t.type ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , t.index ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , t.next ); } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testUnusedEnums( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "test" ); d.enumeration( T_String( "Blah" ) ) << "a" << "b"; } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , c.enums.size( ) ); } void SRDParserConfigTest::testUnusedContexts( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "test" ); d.context( T_String( "other" ) ) << ( Rule( ) << "test" ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.contexts.size( ) ); CPPUNIT_ASSERT( c.contexts[ 0 ].name( ) == T_String( "test" ) ); } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testContextInheritance( ) { const T_String n0( T_String::Pooled( "test" ) ); const T_String n1( T_String::Pooled( "child" ) ); T_SRDParserDefs d( n0 ); { using namespace SRD; d.context( n0 ) << ( Rule( ) << "a" ); d.context( n1 , n0 ) << ( Rule( ) << "a" << "b" << "a" ) << ( Rule( ) << ( Between( 3 , 5 ) << "a" ) ); d.defaultContext( n1 ); } T_SRDParserConfig c( d ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , c.contexts.size( ) ); CPPUNIT_ASSERT( c.contexts[ 0 ].name( ) == n1 ); checkMergedRules( c ); } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testErrorMissingCtxRule( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "a" << EnterContext( "nope" ) ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorMissingCtxParent( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "fail" ) , T_String( "parent" ) ) << ( Rule( ) << "a" ); d.defaultContext( T_String( "fail" ) ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorMissingEnum( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << Enum( "nope" ) ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorEmptyContext( ) { T_SRDParserDefs d( T_String( "test" ) ); CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorEmptyRule( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << Rule( ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorEmptyAlt( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << Alt( ) ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorEmptyRepeat( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << Opt( ) ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorRecursiveInheritance( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "fail" ) , T_String( "parent" ) ) << ( Rule( ) << "a" ); d.context( T_String( "parent" ) , T_String( "fail" ) ) << ( Rule( ) << "b" ); d.defaultContext( T_String( "fail" ) ); } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorAmbiguousRules( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << ( AtLeast( 1 ) << "a" ) ) << ( Rule( ) << "a" ) ; } CPPUNIT_ASSERT_THROW( NewOwned< T_SRDParserConfig >( d ) , X_SRDParserConfig ); } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testErrorUBRSimpleOK( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << LStart( ) << "a" << LEnd( ) ) ; } T_SRDParserConfig{ d }; } void SRDParserConfigTest::testErrorUBRSimpleUnbalancedStart( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << LStart( ) << "a" ) ; } CPPUNIT_ASSERT_THROW( T_SRDParserConfig{ d } , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorUBRSimpleUnbalancedEnd( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << "a" << LEnd( ) ) ; } CPPUNIT_ASSERT_THROW( T_SRDParserConfig{ d } , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorUBRAltsOKContained( ) { T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.context( T_String( "test" ) ) << ( Rule( ) << ( Alt( ) << ( Sub( ) << LStart( ) << "a" << LEnd( ) ) << ( Sub( ) << LStart( ) << "b" << LEnd( ) ) << "c" ) ) ; } T_SRDParserConfig{ d }; } void SRDParserConfigTest::testErrorUBRAltsOKBalancing( ) { T_SRDParserDefs d( "test" ); { using namespace SRD; d.context( "test" ) << ( Rule( ) << ( Alt( ) << ( Sub( ) << LStart( ) << "a" ) << ( Sub( ) << LStart( ) << "b" ) ) << "c" << ( Alt( ) << ( Sub( ) << "d" << LEnd( ) ) << ( Sub( ) << "e" << LEnd( ) ) ) ) ; } T_SRDParserConfig{ d }; } void SRDParserConfigTest::testErrorUBRAltsDifferent( ) { T_SRDParserDefs d( "test" ); { using namespace SRD; d.context( "test" ) << ( Rule( ) << ( Alt( ) << LStart( ) << LEnd( ) ) ); } CPPUNIT_ASSERT_THROW( T_SRDParserConfig{ d } , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorUBRAltsUnbalanced( ) { T_SRDParserDefs d( "test" ); { using namespace SRD; d.context( "test" ) << ( Rule( ) << ( Alt( ) << ( Sub( ) << LStart( ) << "a" ) << ( Sub( ) << LStart( ) << "b" ) ) ); } CPPUNIT_ASSERT_THROW( T_SRDParserConfig{ d } , X_SRDParserConfig ); } void SRDParserConfigTest::testErrorUBRRepsOK( ) { T_SRDParserDefs d( "test" ); { using namespace SRD; d.context( "test" ) << ( Rule( ) << ( Times( 5 ) << LStart( ) ) << ( Times( 3 ) << LEnd( ) ) << LEnd( ) << LEnd( ) ); } T_SRDParserConfig{ d }; } void SRDParserConfigTest::testErrorUBRRepsUnbalanced( ) { T_SRDParserDefs d( "test" ); { using namespace SRD; d.context( "test" ) << ( Rule( ) << ( Between( 1 , 5 ) << LStart( ) ) << ( Between( 1 , 5 ) << LEnd( ) ) ); } CPPUNIT_ASSERT_THROW( T_SRDParserConfig{ d } , X_SRDParserConfig ); } /*----------------------------------------------------------------------------*/ void SRDParserConfigTest::testTransition( ) { #define M_DO_TRANS( STATE , TOK ) \ uint32_t state( STATE ); \ bool result = c.transition( state , TOK ) #define M_CHECK_TRANS_OK( STATE , TOK , OUT ) \ do { \ M_DO_TRANS( STATE , TOK ); \ CPPUNIT_ASSERT( result ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( OUT ) , state ); \ } while ( 0 ) #define M_CHECK_TRANS_FAIL( STATE , TOK ) \ do { \ M_DO_TRANS( STATE , TOK ); \ CPPUNIT_ASSERT( !result ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( STATE ) , state ); \ } while ( 0 ) T_SRDParserDefs d( T_String( "test" ) ); { using namespace SRD; d.enumeration( T_String( "test" ) ) << "a" << "b"; d.context( T_String( "test" ) ) << ( Rule( ) << Int32( ) << "a" << Enum( "test" ) << Word( ) << ( Alt( ) << ( Sub( ) << "a" << "a" ) << ( Sub( ) << Enum( "test" ) << "b" ) << ( Sub( ) << Word( ) << "c" ) ) ) ; } T_SRDParserConfig c( d ); T_SRDToken tInt( T_SRDToken::Integer( 1 ) ) , tWordA( T_SRDToken::Word( T_String( "a" ) ) ) , tWordB( T_SRDToken::Word( T_String( "b" ) ) ) , tWordC( T_SRDToken::Word( T_String( "c" ) ) ); M_CHECK_TRANS_OK( 0 , tInt , 1 ); M_CHECK_TRANS_FAIL( 0 , tWordA ); M_CHECK_TRANS_FAIL( 1 , tInt ); M_CHECK_TRANS_OK( 1 , tWordA , 2 ); M_CHECK_TRANS_FAIL( 1 , tWordB ); M_CHECK_TRANS_FAIL( 2 , tInt ); M_CHECK_TRANS_OK( 2 , tWordA , 3 ); M_CHECK_TRANS_OK( 2 , tWordB , 3 ); M_CHECK_TRANS_FAIL( 2 , tWordC ); M_CHECK_TRANS_FAIL( 3 , tInt ); M_CHECK_TRANS_OK( 3 , tWordA , 4 ); M_CHECK_TRANS_OK( 3 , tWordB , 4 ); M_CHECK_TRANS_OK( 3 , tWordC , 4 ); M_CHECK_TRANS_FAIL( 4 , tInt ); M_CHECK_TRANS_OK( 4 , tWordA , 6 ); M_CHECK_TRANS_OK( 4 , tWordB , 7 ); M_CHECK_TRANS_OK( 4 , tWordC , 5 ); }