altium: introduce tokenizer for query language

Based on this tokenizer, a LL1 parser will be built in the future.
This commit is contained in:
Thomas Pointhuber 2021-03-21 16:37:02 +01:00
parent b25103ccf1
commit 68f3d09ac1
5 changed files with 756 additions and 1 deletions

View File

@ -5,8 +5,9 @@ set( ALTIUM2PCBNEW_SRCS
altium_circuit_maker_plugin.cpp
altium_circuit_studio_plugin.cpp
altium_designer_plugin.cpp
altium_pcb.cpp
altium_parser_pcb.cpp
altium_pcb.cpp
altium_rule_transformer.cpp
)
add_library( altium2pcbnew STATIC ${ALTIUM2PCBNEW_SRCS} )

View File

@ -0,0 +1,221 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 Thomas Pointhuber <thomas.pointhuber@gmx.at>
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "altium_rule_transformer.h"
#include <iostream>
const ALTIUM_RULE_TOKEN& ALTIUM_RULE_TOKENIZER::Next()
{
m_currentToken = m_nextToken;
// skip whitespaces
for( ; m_it != m_expr.end() && wxIsspace( curChar() ); nextChar() )
;
// check for end of string
if( m_it == m_expr.end() )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, m_pos };
return m_currentToken;
}
const size_t startPos = m_pos;
const wxUniChar curCh = curChar();
wxUniChar nextCh = nextChar();
if( curCh == '(' )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::LPAR, startPos };
return m_currentToken;
}
else if( curCh == ')' )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::RPAR, startPos };
return m_currentToken;
}
else if( curCh == '*' )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::MUL, startPos };
return m_currentToken;
}
else if( curCh == '/' )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::DIV, startPos };
return m_currentToken;
}
else if( curCh == '=' )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::EQUAL, startPos };
return m_currentToken;
}
else if( curCh == '<' )
{
if( nextCh == '=' )
{
nextChar();
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::LESS_EQUAL, startPos };
}
else if( nextCh == '>' )
{
nextChar();
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::NOT_EQUAL, startPos };
}
else
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::LESS, startPos };
}
return m_currentToken;
}
else if( curCh == '>' )
{
if( nextCh == '=' )
{
nextChar();
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::GREATER_EQUAL, startPos };
}
else
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::GREATER, startPos };
}
return m_currentToken;
}
else if( curCh == '&' && nextCh == '&' )
{
nextChar();
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::LOW_AND, startPos };
return m_currentToken;
}
else if( curCh == '|' && nextCh == '|' )
{
nextChar();
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::LOW_OR, startPos };
return m_currentToken;
}
else if( curCh == '\'' )
{
std::cout << "start const string" << std::endl;
wxString constString;
while( m_it != m_expr.end() && nextCh != '\'' )
{
constString += nextCh; // TODO: escaping?
nextCh = nextChar();
}
std::cout << "end const string: " << constString << std::endl;
if( m_it != m_expr.end() )
{
nextChar(); // TODO: exception if EOF reached?
}
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::CONST_STRING, startPos, constString };
return m_currentToken;
}
else if( curCh == '+' && !wxIsdigit( nextCh ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::ADD, startPos };
return m_currentToken;
}
else if( curCh == '-' && !wxIsdigit( nextCh ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::SUB, startPos };
return m_currentToken;
}
else if( curCh == '+' || curCh == '-' || wxIsdigit( curCh ) )
{
wxString digitString = curCh;
while( wxIsdigit( nextCh ) )
{
digitString += nextCh;
nextCh = nextChar();
}
long value;
digitString.ToLong( &value ); // TODO: check return value
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::CONST_INT, startPos, value };
return m_currentToken;
}
else
{
wxString identString = curCh;
while( wxIsalnum( nextCh ) )
{
identString += nextCh;
nextCh = nextChar();
}
if( identString.IsSameAs( "True", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::CONST_TRUE, startPos };
}
else if( identString.IsSameAs( "False", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::CONST_FALSE, startPos };
}
else if( identString.IsSameAs( "Div", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::INTEGRAL_DIV, startPos };
}
else if( identString.IsSameAs( "Mod", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::MOD, startPos };
}
else if( identString.IsSameAs( "And", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::AND, startPos };
}
else if( identString.IsSameAs( "Or", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::OR, startPos };
}
else if( identString.IsSameAs( "Xor", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::XOR, startPos };
}
else if( identString.IsSameAs( "Not", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::NOT, startPos };
}
else if( identString.IsSameAs( "Between", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::BETWEEN, startPos };
}
else if( identString.IsSameAs( "Like", false ) )
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::LIKE, startPos };
}
else
{
m_nextToken = { ALTIUM_RULE_TOKEN_KIND::IDENT, startPos, identString };
}
return m_currentToken;
}
}
const ALTIUM_RULE_TOKEN& ALTIUM_RULE_TOKENIZER::Peek() const
{
return m_nextToken;
}

View File

@ -0,0 +1,143 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 Thomas Pointhuber <thomas.pointhuber@gmx.at>
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef ALTIUM_RULE_TRANSFORMER_H
#define ALTIUM_RULE_TRANSFORMER_H
#include "wx/string.h"
// See: https://www.altium.com/documentation/altium-designer/query-operators-ad
enum class ALTIUM_RULE_TOKEN_KIND
{
UNKNOWN,
IDENT,
CONST_INT,
CONST_FLOAT,
CONST_STRING,
CONST_TRUE,
CONST_FALSE,
LPAR,
RPAR,
ADD,
SUB,
MUL,
DIV,
INTEGRAL_DIV,
MOD,
AND,
LOW_AND,
OR,
LOW_OR,
XOR,
NOT,
LESS,
LESS_EQUAL,
GREATER_EQUAL,
GREATER,
NOT_EQUAL,
EQUAL,
BETWEEN,
LIKE,
END_OF_EXPR
};
struct ALTIUM_RULE_TOKEN
{
ALTIUM_RULE_TOKEN_KIND kind;
size_t pos;
long iValue;
double fValue;
wxString sValue;
ALTIUM_RULE_TOKEN() :
kind( ALTIUM_RULE_TOKEN_KIND::UNKNOWN ), pos( 0 ), iValue( 0 ), fValue( 0. ),
sValue( "" )
{
}
ALTIUM_RULE_TOKEN( ALTIUM_RULE_TOKEN_KIND aKind, size_t aPos ) :
kind( aKind ), pos( aPos ), iValue( 0 ), fValue( 0. ), sValue( "" )
{
}
ALTIUM_RULE_TOKEN( ALTIUM_RULE_TOKEN_KIND aKind, size_t aPos, long aValue ) :
kind( aKind ), pos( aPos ), iValue( aValue ), fValue( 0. ), sValue( "" )
{
}
ALTIUM_RULE_TOKEN( ALTIUM_RULE_TOKEN_KIND aKind, size_t aPos, float aValue ) :
kind( aKind ), pos( aPos ), iValue( 0 ), fValue( aValue ), sValue( "" )
{
}
ALTIUM_RULE_TOKEN( ALTIUM_RULE_TOKEN_KIND aKind, size_t aPos, wxString aValue ) :
kind( aKind ), pos( aPos ), iValue( 0 ), fValue( 0. ), sValue( aValue )
{
}
};
class ALTIUM_RULE_TOKENIZER
{
public:
ALTIUM_RULE_TOKENIZER( const wxString& aExpr ) : m_pos( 0 ), m_expr( aExpr )
{
m_it = m_expr.begin();
Next();
}
const ALTIUM_RULE_TOKEN& Next();
const ALTIUM_RULE_TOKEN& Peek() const;
private:
wxUniChar curChar() { return *m_it; }
wxUniChar nextChar()
{
if( m_it != m_expr.end() )
{
m_pos++;
}
return *( ++m_it );
}
size_t m_pos;
const wxString m_expr;
wxString::const_iterator m_it;
ALTIUM_RULE_TOKEN m_currentToken;
ALTIUM_RULE_TOKEN m_nextToken;
};
#endif //ALTIUM_RULE_TRANSFORMER_H

View File

@ -41,6 +41,8 @@ set( QA_PCBNEW_SRCS
drc/test_drc_courtyard_invalid.cpp
drc/test_drc_courtyard_overlap.cpp
plugins/altium/test_altium_rule_transformer.cpp
group_saveload.cpp
)

View File

@ -0,0 +1,388 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file test_altium_rule_transformer.cpp
* Test suite for #ALTIUM_RULE_TOKENIZER
*/
#include <unit_test_utils/unit_test_utils.h>
#include <pcbnew/plugins/altium/altium_rule_transformer.h>
struct ALTIUM_RULE_TRANSFORMER_FIXTURE
{
ALTIUM_RULE_TRANSFORMER_FIXTURE() {}
};
/**
* Declares the struct as the Boost test fixture.
*/
BOOST_FIXTURE_TEST_SUITE( AltiumRuleTransformer, ALTIUM_RULE_TRANSFORMER_FIXTURE )
BOOST_AUTO_TEST_CASE( AltiumRuleTokenizerEmptyInput )
{
ALTIUM_RULE_TOKENIZER tokenizer( "" );
const ALTIUM_RULE_TOKEN& peek = tokenizer.Peek();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == peek.kind ) );
BOOST_CHECK_EQUAL( 0, peek.pos );
const ALTIUM_RULE_TOKEN& next = tokenizer.Next();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == next.kind ) );
BOOST_CHECK_EQUAL( 0, next.pos );
const ALTIUM_RULE_TOKEN& peek2 = tokenizer.Peek();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == peek2.kind ) );
BOOST_CHECK_EQUAL( 0, peek2.pos );
}
BOOST_AUTO_TEST_CASE( AltiumRuleTokenizerOnlySpaces )
{
ALTIUM_RULE_TOKENIZER tokenizer( " " );
const ALTIUM_RULE_TOKEN& peek = tokenizer.Peek();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == peek.kind ) );
BOOST_CHECK_EQUAL( 3, peek.pos );
const ALTIUM_RULE_TOKEN& next = tokenizer.Next();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == next.kind ) );
BOOST_CHECK_EQUAL( 3, next.pos );
const ALTIUM_RULE_TOKEN& peek2 = tokenizer.Peek();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == peek2.kind ) );
BOOST_CHECK_EQUAL( 3, peek2.pos );
}
BOOST_AUTO_TEST_CASE( AltiumRuleTokenizerSingleCharIdentifier )
{
ALTIUM_RULE_TOKENIZER tokenizer( "a" );
const ALTIUM_RULE_TOKEN& next = tokenizer.Next();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::IDENT == next.kind ) );
BOOST_CHECK_EQUAL( 0, next.pos );
BOOST_CHECK_EQUAL( "a", next.sValue );
const ALTIUM_RULE_TOKEN& peek = tokenizer.Peek();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == peek.kind ) );
BOOST_CHECK_EQUAL( 1, peek.pos );
const ALTIUM_RULE_TOKEN& next2 = tokenizer.Next();
BOOST_CHECK( ( ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR == next2.kind ) );
BOOST_CHECK_EQUAL( 1, next2.pos );
}
struct ALTIUM_RULE_TOKENIZER_INPUT_OUTPUT
{
wxString input;
std::vector<ALTIUM_RULE_TOKEN> exp_token;
};
/**
* A list of valid test strings and the expected results
*/
static const std::vector<ALTIUM_RULE_TOKENIZER_INPUT_OUTPUT> altium_rule_tokens_property = {
// Empty string
{ "",
{
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 0 }
}
},
// Single Token
{ "All",
{
{ ALTIUM_RULE_TOKEN_KIND::IDENT, 0, "All" },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "1234",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_INT, 0, 1234L },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 4 }
}
},
{ "+1234",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_INT, 0, 1234L },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 5 }
}
},
{ "-1234",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_INT, 0, -1234L },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 5 }
}
},
{ "'1234'",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_STRING, 0, "1234" },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 6 }
}
},
{ "True",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_TRUE, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 4 }
}
},
{ "true",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_TRUE, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 4 }
}
},
{ "False",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_FALSE, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 5 }
}
},
{ "false",
{
{ ALTIUM_RULE_TOKEN_KIND::CONST_FALSE, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 5 }
}
},
{ "+",
{
{ ALTIUM_RULE_TOKEN_KIND::ADD, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ "-",
{
{ ALTIUM_RULE_TOKEN_KIND::SUB, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ "*",
{
{ ALTIUM_RULE_TOKEN_KIND::MUL, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ "/",
{
{ ALTIUM_RULE_TOKEN_KIND::DIV, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ "Div",
{
{ ALTIUM_RULE_TOKEN_KIND::INTEGRAL_DIV, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "div",
{
{ ALTIUM_RULE_TOKEN_KIND::INTEGRAL_DIV, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "Mod",
{
{ ALTIUM_RULE_TOKEN_KIND::MOD, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "mod",
{
{ ALTIUM_RULE_TOKEN_KIND::MOD, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "And",
{
{ ALTIUM_RULE_TOKEN_KIND::AND, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "and",
{
{ ALTIUM_RULE_TOKEN_KIND::AND, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "&&",
{
{ ALTIUM_RULE_TOKEN_KIND::LOW_AND, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ "Or",
{
{ ALTIUM_RULE_TOKEN_KIND::OR, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ "or",
{
{ ALTIUM_RULE_TOKEN_KIND::OR, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ "||",
{
{ ALTIUM_RULE_TOKEN_KIND::LOW_OR, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ "Xor",
{
{ ALTIUM_RULE_TOKEN_KIND::XOR, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "xor",
{
{ ALTIUM_RULE_TOKEN_KIND::XOR, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "Not",
{
{ ALTIUM_RULE_TOKEN_KIND::NOT, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "not",
{
{ ALTIUM_RULE_TOKEN_KIND::NOT, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 3 }
}
},
{ "<",
{
{ ALTIUM_RULE_TOKEN_KIND::LESS, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ "<=",
{
{ ALTIUM_RULE_TOKEN_KIND::LESS_EQUAL, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ ">",
{
{ ALTIUM_RULE_TOKEN_KIND::GREATER, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ ">=",
{
{ ALTIUM_RULE_TOKEN_KIND::GREATER_EQUAL, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ "<>",
{
{ ALTIUM_RULE_TOKEN_KIND::NOT_EQUAL, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 2 }
}
},
{ "=",
{
{ ALTIUM_RULE_TOKEN_KIND::EQUAL, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 1 }
}
},
{ "Between",
{
{ ALTIUM_RULE_TOKEN_KIND::BETWEEN, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 7 }
}
},
{ "between",
{
{ ALTIUM_RULE_TOKEN_KIND::BETWEEN, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 7 }
}
},
{ "Like",
{
{ ALTIUM_RULE_TOKEN_KIND::LIKE, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 4 }
}
},
{ "like",
{
{ ALTIUM_RULE_TOKEN_KIND::LIKE, 0 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 4 }
}
},
// Multiple tokens
{ "ab cd ef",
{
{ ALTIUM_RULE_TOKEN_KIND::IDENT, 0, "ab" },
{ ALTIUM_RULE_TOKEN_KIND::IDENT, 3, "cd" },
{ ALTIUM_RULE_TOKEN_KIND::IDENT, 6, "ef" },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 8 }
}
},
// Complex tests
{ "InComponent('LEDS1') or InComponent('LEDS2')",
{
{ ALTIUM_RULE_TOKEN_KIND::IDENT, 0, "InComponent" },
{ ALTIUM_RULE_TOKEN_KIND::LPAR, 11 },
{ ALTIUM_RULE_TOKEN_KIND::CONST_STRING, 12, "LEDS1" },
{ ALTIUM_RULE_TOKEN_KIND::RPAR, 19 },
{ ALTIUM_RULE_TOKEN_KIND::OR, 21 },
{ ALTIUM_RULE_TOKEN_KIND::IDENT, 24, "InComponent" },
{ ALTIUM_RULE_TOKEN_KIND::LPAR, 35 },
{ ALTIUM_RULE_TOKEN_KIND::CONST_STRING, 36, "LEDS2" },
{ ALTIUM_RULE_TOKEN_KIND::RPAR, 43 },
{ ALTIUM_RULE_TOKEN_KIND::END_OF_EXPR, 44 }
}
}
};
/**
* Test conversation from wxString to Altium tokens
*/
BOOST_AUTO_TEST_CASE( AltiumRuleTokenizerParameterizedTest )
{
for( const auto& c : altium_rule_tokens_property )
{
BOOST_TEST_CONTEXT( wxString::Format( wxT( "'%s'" ), c.input ) )
{
ALTIUM_RULE_TOKENIZER tokenizer( c.input );
for( const auto& expected : c.exp_token )
{
const ALTIUM_RULE_TOKEN& token = tokenizer.Next();
BOOST_CHECK( ( expected.kind == token.kind ) );
BOOST_CHECK_EQUAL( expected.pos, token.pos );
BOOST_CHECK_EQUAL( expected.iValue, token.iValue );
BOOST_CHECK_EQUAL( expected.fValue, token.fValue );
BOOST_CHECK_EQUAL( expected.sValue, token.sValue );
}
}
}
}
BOOST_AUTO_TEST_SUITE_END()