Report all DRC rule errors, not just the first.
This commit is contained in:
parent
ebef7c03db
commit
577c1be391
|
@ -10,10 +10,6 @@ graphic
|
|||
hole
|
||||
inner
|
||||
layer
|
||||
match_area
|
||||
match_layer
|
||||
match_netclass
|
||||
match_type
|
||||
max
|
||||
micro_via
|
||||
min
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#include <reporter.h>
|
||||
#include <libeval_compiler/libeval_compiler.h>
|
||||
|
||||
/* The (generated) lemon parser is written in C.
|
||||
|
@ -150,13 +151,6 @@ std::string UCODE::Dump() const
|
|||
};
|
||||
|
||||
|
||||
void CONTEXT::ReportError( const wxString& aErrorMsg )
|
||||
{
|
||||
m_errorStatus.pendingError = true;
|
||||
m_errorStatus.message = aErrorMsg;
|
||||
}
|
||||
|
||||
|
||||
std::string TOKENIZER::GetChars( std::function<bool( int )> cond ) const
|
||||
{
|
||||
std::string rv;
|
||||
|
@ -186,7 +180,10 @@ bool TOKENIZER::MatchAhead( const std::string& match, std::function<bool( int )>
|
|||
}
|
||||
|
||||
|
||||
COMPILER::COMPILER()
|
||||
COMPILER::COMPILER( REPORTER* aReporter, int aSourceLine, int aSourceOffset ) :
|
||||
m_reporter( aReporter ),
|
||||
m_originLine( aSourceLine ),
|
||||
m_originOffset( aSourceOffset )
|
||||
{
|
||||
m_localeDecimalSeparator = '.';
|
||||
m_sourcePos = 0;
|
||||
|
@ -224,9 +221,7 @@ void COMPILER::Clear()
|
|||
|
||||
void COMPILER::parseError( const char* s )
|
||||
{
|
||||
libeval_dbg(0, "PARSE ERROR: %s\n", s );
|
||||
m_errorStatus.pendingError = true;
|
||||
m_errorStatus.message = s;
|
||||
reportError( s );
|
||||
}
|
||||
|
||||
|
||||
|
@ -241,7 +236,6 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPref
|
|||
// Feed parser token after token until end of input.
|
||||
|
||||
newString( aString );
|
||||
m_errorStatus.pendingError = false;
|
||||
|
||||
if( m_tree )
|
||||
{
|
||||
|
@ -268,14 +262,6 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPref
|
|||
libeval_dbg(10, "parse: tok %d\n", tok.token );
|
||||
Parse( m_parser, tok.token, tok.value, this );
|
||||
|
||||
if( m_errorStatus.pendingError )
|
||||
{
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_PARSE;
|
||||
m_errorStatus.message.Printf( _( "Unrecognized token '%s'" ), tok.value.value.str );
|
||||
m_errorStatus.srcPos = m_tokenizer.GetPos();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_parseFinished || tok.token == G_ENDS )
|
||||
{
|
||||
// Reset parser by passing zero as token ID, value is ignored.
|
||||
|
@ -359,6 +345,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
|
|||
T_TOKEN retval;
|
||||
std::string current;
|
||||
int convertFrom;
|
||||
wxString msg;
|
||||
|
||||
retval.token = G_ENDS;
|
||||
|
||||
|
@ -495,8 +482,6 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
|
|||
}
|
||||
else
|
||||
{
|
||||
//printf( "WTF: '%c'\n", ch );
|
||||
|
||||
// Single char tokens
|
||||
switch( ch )
|
||||
{
|
||||
|
@ -513,9 +498,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
|
|||
case '.': retval.token = G_STRUCT_REF; break;
|
||||
|
||||
default:
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_PARSE;
|
||||
m_errorStatus.message.Printf( _( "Unrecognized character '%c'" ), (char) ch );
|
||||
m_errorStatus.srcPos = m_tokenizer.GetPos();
|
||||
reportError( wxString::Format( _( "Unrecognized character '%c'" ), (char) ch ) );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -526,6 +509,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
const std::string formatNode( TREE_NODE* tok )
|
||||
{
|
||||
// printf("fmt tok %p v %p ", tok, tok->value.v );
|
||||
|
@ -598,10 +582,20 @@ void dumpNode( std::string& buf, TREE_NODE* tok, int depth = 0 )
|
|||
}
|
||||
|
||||
|
||||
void COMPILER::ReportError( const wxString& aErrorMsg )
|
||||
void COMPILER::reportError( const wxString& aErrorMsg, int aPos )
|
||||
{
|
||||
m_errorStatus.pendingError = true;
|
||||
m_errorStatus.message = aErrorMsg;
|
||||
if( aPos == -1 )
|
||||
aPos = m_sourcePos;
|
||||
|
||||
wxString rest;
|
||||
wxString first = aErrorMsg.BeforeFirst( '|', &rest );
|
||||
wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
|
||||
m_originLine,
|
||||
m_originOffset + aPos,
|
||||
first,
|
||||
rest );
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
|
||||
|
@ -624,6 +618,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
{
|
||||
std::vector<TREE_NODE*> stack;
|
||||
std::set<TREE_NODE*> visitedNodes;
|
||||
wxString msg;
|
||||
|
||||
auto visited = [&]( TREE_NODE* node ) -> bool
|
||||
{
|
||||
|
@ -663,26 +658,19 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
{
|
||||
char* itemName = node->leaf[0]->value.str;
|
||||
char* propName = node->leaf[1]->value.str;
|
||||
VAR_REF* vref = aCode->createVarRef( this, itemName, propName );
|
||||
VAR_REF* vref = aCode->CreateVarRef( itemName, propName );
|
||||
|
||||
if( m_errorStatus.pendingError )
|
||||
if( !vref )
|
||||
{
|
||||
m_errorStatus.pendingError = true;
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_CODEGEN;
|
||||
|
||||
if( m_errorStatus.message == "var" )
|
||||
{
|
||||
m_errorStatus.message.Printf( _( "Unrecognized item '%s'" ),
|
||||
itemName );
|
||||
m_errorStatus.srcPos = node->leaf[0]->srcPos - strlen( itemName );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorStatus.message.Printf( _( "Unrecognized property '%s'" ),
|
||||
propName );
|
||||
m_errorStatus.srcPos = node->leaf[1]->srcPos - strlen( propName );
|
||||
msg.Printf( _( "Unrecognized item '%s'" ), itemName );
|
||||
reportError( msg, node->leaf[0]->srcPos - (int) strlen( itemName ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( vref->GetType() == VT_PARSE_ERROR )
|
||||
{
|
||||
msg.Printf( _( "Unrecognized property '%s'" ), propName );
|
||||
reportError( msg, node->leaf[1]->srcPos - (int) strlen( propName ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -693,26 +681,22 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
case TR_OP_FUNC_CALL:
|
||||
{
|
||||
char* itemName = node->leaf[0]->value.str;
|
||||
VAR_REF* vref = aCode->createVarRef( this, itemName, "" );
|
||||
VAR_REF* vref = aCode->CreateVarRef( itemName, "" );
|
||||
|
||||
if( m_errorStatus.pendingError )
|
||||
if( !vref )
|
||||
{
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_CODEGEN;
|
||||
m_errorStatus.message.Printf( _( "Unrecognized item '%s'" ), itemName );
|
||||
m_errorStatus.srcPos = node->leaf[0]->srcPos - strlen( itemName );
|
||||
msg.Printf( _( "Unrecognized item '%s'" ), itemName );
|
||||
reportError( msg, node->leaf[0]->srcPos - (int) strlen( itemName ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
char* functionName = node->leaf[1]->leaf[0]->value.str;
|
||||
auto func = aCode->createFuncCall( this, functionName );
|
||||
auto func = aCode->CreateFuncCall( functionName );
|
||||
|
||||
if( !func )
|
||||
{
|
||||
m_errorStatus.pendingError = true;
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_CODEGEN;
|
||||
m_errorStatus.message.Printf( _( "Unrecognized function '%s'" ),
|
||||
functionName );
|
||||
m_errorStatus.srcPos = node->leaf[1]->leaf[0]->srcPos + 1;
|
||||
msg.Printf( _( "Unrecognized function '%s'" ), functionName );
|
||||
reportError( msg, node->leaf[1]->leaf[0]->srcPos + 1 );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -730,18 +714,18 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
{
|
||||
}
|
||||
|
||||
if( aPreflightContext->GetErrorStatus().pendingError )
|
||||
{
|
||||
m_errorStatus = aPreflightContext->GetErrorStatus();
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_CODEGEN;
|
||||
m_errorStatus.srcPos = node->leaf[1]->leaf[0]->srcPos + 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* SREF -> FUNC_CALL -> leaf0/1 */
|
||||
node->leaf[1]->leaf[0]->leaf[0] = nullptr;
|
||||
node->leaf[1]->leaf[0]->leaf[1] = nullptr;
|
||||
|
||||
if( !aPreflightContext->GetError().IsEmpty() )
|
||||
{
|
||||
reportError( aPreflightContext->GetError(),
|
||||
node->leaf[1]->leaf[1]->srcPos
|
||||
- (int) strlen( node->value.str ) - 1 );
|
||||
return false;
|
||||
}
|
||||
|
||||
visitedNodes.insert( node->leaf[0] );
|
||||
visitedNodes.insert( node->leaf[1]->leaf[0] );
|
||||
|
||||
|
@ -782,20 +766,12 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
|
||||
case TR_IDENTIFIER:
|
||||
{
|
||||
VAR_REF* vref = aCode->createVarRef( this, node->value.str, "" );
|
||||
VAR_REF* vref = aCode->CreateVarRef( node->value.str, "" );
|
||||
|
||||
if( m_errorStatus.pendingError )
|
||||
if( !vref )
|
||||
{
|
||||
m_errorStatus.pendingError = true;
|
||||
m_errorStatus.stage = ERROR_STATUS::CST_CODEGEN;
|
||||
|
||||
if( m_errorStatus.message == "var" )
|
||||
{
|
||||
m_errorStatus.message.Printf( _( "Unrecognized item '%s'" ),
|
||||
node->value.str );
|
||||
m_errorStatus.srcPos = node->srcPos - strlen( node->value.str );
|
||||
}
|
||||
|
||||
msg.Printf( _( "Unrecognized item '%s'" ), node->value.str );
|
||||
reportError( msg, node->leaf[0]->srcPos - (int) strlen( node->value.str ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,8 @@ enum VAR_TYPE_T
|
|||
{
|
||||
VT_STRING = 1,
|
||||
VT_NUMERIC,
|
||||
VT_UNDEFINED
|
||||
VT_UNDEFINED,
|
||||
VT_PARSE_ERROR
|
||||
};
|
||||
|
||||
enum TOKEN_TYPE_T
|
||||
|
@ -287,13 +288,13 @@ public:
|
|||
return m_stack.size();
|
||||
}
|
||||
|
||||
ERROR_STATUS GetErrorStatus() const { return m_errorStatus; }
|
||||
void ReportError( const wxString& aErrorMsg );
|
||||
void ReportError( const wxString& aErrorMsg ) { m_errorMessage = aErrorMsg; }
|
||||
const wxString& GetError() const { return m_errorMessage; }
|
||||
|
||||
private:
|
||||
std::vector<VALUE*> m_ownedValues;
|
||||
std::stack<VALUE*> m_stack;
|
||||
ERROR_STATUS m_errorStatus;
|
||||
wxString m_errorMessage;
|
||||
};
|
||||
|
||||
|
||||
|
@ -312,12 +313,12 @@ public:
|
|||
VALUE* Run( CONTEXT* ctx );
|
||||
std::string Dump() const;
|
||||
|
||||
virtual VAR_REF* createVarRef( COMPILER* aCompiler, const char* var, const char* field )
|
||||
virtual VAR_REF* CreateVarRef( const char* var, const char* field )
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
virtual FUNC_PTR createFuncCall( COMPILER* aCompiler, const char* name )
|
||||
virtual FUNC_PTR CreateFuncCall( const char* name )
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
@ -402,7 +403,7 @@ private:
|
|||
class COMPILER
|
||||
{
|
||||
public:
|
||||
COMPILER();
|
||||
COMPILER( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
||||
virtual ~COMPILER();
|
||||
|
||||
/*
|
||||
|
@ -417,18 +418,10 @@ public:
|
|||
|
||||
int GetSourcePos() const { return m_sourcePos; }
|
||||
|
||||
/* Check if previous invokation of process() was successful */
|
||||
inline bool IsValid() const
|
||||
{
|
||||
return !m_errorStatus.pendingError;
|
||||
}
|
||||
|
||||
void setRoot( LIBEVAL::TREE_NODE root );
|
||||
void freeTree( LIBEVAL::TREE_NODE *tree );
|
||||
|
||||
bool Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPreflightContext );
|
||||
void ReportError( const wxString& aErrorMsg );
|
||||
ERROR_STATUS GetErrorStatus() const { return m_errorStatus; }
|
||||
|
||||
protected:
|
||||
enum LEXER_STATE
|
||||
|
@ -441,6 +434,7 @@ protected:
|
|||
|
||||
bool generateUCode( UCODE* aCode, CONTEXT* aPreflightContext );
|
||||
|
||||
void reportError( const wxString& aErrorMsg, int aPos = -1 );
|
||||
|
||||
/* Token type used by the tokenizer */
|
||||
struct T_TOKEN
|
||||
|
@ -483,8 +477,8 @@ protected:
|
|||
return uop;
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Token state for input string. */
|
||||
|
||||
void* m_parser; // the current lemon parser state machine
|
||||
TOKENIZER m_tokenizer;
|
||||
char m_localeDecimalSeparator;
|
||||
|
@ -492,9 +486,12 @@ protected:
|
|||
std::unique_ptr<UNIT_RESOLVER> m_unitResolver;
|
||||
|
||||
int m_sourcePos;
|
||||
ERROR_STATUS m_errorStatus;
|
||||
bool m_parseFinished;
|
||||
|
||||
REPORTER* m_reporter;
|
||||
int m_originLine; // Location in the file of the start of the expression
|
||||
int m_originOffset;
|
||||
|
||||
TREE_NODE* m_tree;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <widgets/paged_dialog.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <pcb_expr_evaluator.h>
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include <tool/tool_manager.h>
|
||||
#include <drc/drc.h>
|
||||
#include <panel_setup_rules.h>
|
||||
#include <wx_html_report_box.h>
|
||||
#include <html_messagebox.h>
|
||||
#include <scintilla_tricks.h>
|
||||
#include <drc/drc_rule_parser.h>
|
||||
|
@ -47,6 +49,8 @@ PANEL_SETUP_RULES::PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFr
|
|||
for( size_t i = 0; i < wxSTC_STYLE_MAX; ++i )
|
||||
m_textEditor->StyleSetFont( i, fixedFont );
|
||||
|
||||
m_compileButton->SetBitmap( KiBitmap( reload_xpm ) );
|
||||
|
||||
m_textEditor->Bind( wxEVT_STC_CHARADDED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
|
||||
m_textEditor->Bind( wxEVT_STC_AUTOCOMP_CHAR_DELETED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
|
||||
}
|
||||
|
@ -224,6 +228,49 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
|
|||
}
|
||||
|
||||
|
||||
void PANEL_SETUP_RULES::OnCompile( wxCommandEvent& event )
|
||||
{
|
||||
m_errorsReport->Clear();
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<DRC_RULE*> dummyRules;
|
||||
|
||||
DRC_RULES_PARSER parser( m_frame->GetBoard(), m_textEditor->GetText(), _( "DRC rules" ) );
|
||||
|
||||
parser.Parse( dummyRules, m_errorsReport );
|
||||
}
|
||||
catch( PARSE_ERROR& pe )
|
||||
{
|
||||
m_Parent->SetError( pe.What(), this, m_textEditor, pe.lineNumber, pe.byteIndex );
|
||||
}
|
||||
|
||||
m_errorsReport->Flush();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SETUP_RULES::OnErrorLinkClicked( wxHtmlLinkEvent& event )
|
||||
{
|
||||
wxString link = event.GetLinkInfo().GetHref();
|
||||
wxArrayString parts;
|
||||
int line = 0, offset = 0;
|
||||
|
||||
wxStringSplit( link, parts, ':' );
|
||||
|
||||
if( parts.size() > 1 )
|
||||
{
|
||||
line = (int) strtol( parts[0], nullptr, 10 );
|
||||
offset = (int) strtol( parts[1], nullptr, 10 );
|
||||
}
|
||||
|
||||
int pos = m_textEditor->PositionFromLine( line - 1 ) + ( offset - 1 );
|
||||
|
||||
m_textEditor->GotoPos( pos );
|
||||
|
||||
m_textEditor->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_SETUP_RULES::TransferDataToWindow()
|
||||
{
|
||||
wxString rulesFilepath = m_frame->Prj().AbsolutePath( "drc-rules" );
|
||||
|
@ -249,7 +296,7 @@ bool PANEL_SETUP_RULES::TransferDataFromWindow()
|
|||
|
||||
DRC_RULES_PARSER parser( m_frame->GetBoard(), m_textEditor->GetText(), _( "DRC rules" ) );
|
||||
|
||||
parser.Parse( dummyRules );
|
||||
parser.Parse( dummyRules, m_errorsReport );
|
||||
}
|
||||
catch( PARSE_ERROR& pe )
|
||||
{
|
||||
|
|
|
@ -49,6 +49,8 @@ private:
|
|||
void onScintillaCharAdded( wxStyledTextEvent &aEvent );
|
||||
|
||||
void OnSyntaxHelp( wxHyperlinkEvent& aEvent ) override;
|
||||
void OnCompile( wxCommandEvent& event );
|
||||
void OnErrorLinkClicked( wxHtmlLinkEvent& event ) override;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx_html_report_box.h"
|
||||
|
||||
#include "panel_setup_rules_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -64,7 +66,21 @@ PANEL_SETUP_RULES_BASE::PANEL_SETUP_RULES_BASE( wxWindow* parent, wxWindowID id,
|
|||
m_textEditor->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY );
|
||||
m_textEditor->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
|
||||
m_textEditor->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
|
||||
m_topMargin->Add( m_textEditor, 1, wxEXPAND | wxALL, 5 );
|
||||
m_topMargin->Add( m_textEditor, 3, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxBoxSizer* bSizer5;
|
||||
bSizer5 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_compileButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW|0 );
|
||||
bSizer5->Add( m_compileButton, 0, wxALL, 3 );
|
||||
|
||||
m_errorsReport = new WX_HTML_REPORT_BOX( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO );
|
||||
m_errorsReport->SetMinSize( wxSize( 400,60 ) );
|
||||
|
||||
bSizer5->Add( m_errorsReport, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_topMargin->Add( bSizer5, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_leftMargin->Add( m_topMargin, 1, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
@ -79,11 +95,15 @@ PANEL_SETUP_RULES_BASE::PANEL_SETUP_RULES_BASE( wxWindow* parent, wxWindowID id,
|
|||
|
||||
// Connect Events
|
||||
m_syntaxHelp->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( PANEL_SETUP_RULES_BASE::OnSyntaxHelp ), NULL, this );
|
||||
m_compileButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_RULES_BASE::OnCompile ), NULL, this );
|
||||
m_errorsReport->Connect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( PANEL_SETUP_RULES_BASE::OnErrorLinkClicked ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_SETUP_RULES_BASE::~PANEL_SETUP_RULES_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_syntaxHelp->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( PANEL_SETUP_RULES_BASE::OnSyntaxHelp ), NULL, this );
|
||||
m_compileButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SETUP_RULES_BASE::OnCompile ), NULL, this );
|
||||
m_errorsReport->Disconnect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( PANEL_SETUP_RULES_BASE::OnErrorLinkClicked ), NULL, this );
|
||||
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@
|
|||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<property name="proportion">3</property>
|
||||
<object class="wxStyledTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
|
@ -284,6 +284,149 @@
|
|||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer5</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">3</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">MyButton</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_compileButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size">40,40</property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnCompile</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxHtmlWindow" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">400,60</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_errorsReport</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxHW_SCROLLBAR_AUTO</property>
|
||||
<property name="subclass">WX_HTML_REPORT_BOX; wx_html_report_box.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnHtmlLinkClicked">OnErrorLinkClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class WX_HTML_REPORT_BOX;
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
|
@ -19,6 +21,12 @@
|
|||
#include <wx/hyperlink.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stc/stc.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -38,9 +46,13 @@ class PANEL_SETUP_RULES_BASE : public wxPanel
|
|||
wxStaticText* m_title;
|
||||
wxHyperlinkCtrl* m_syntaxHelp;
|
||||
wxStyledTextCtrl* m_textEditor;
|
||||
wxBitmapButton* m_compileButton;
|
||||
WX_HTML_REPORT_BOX* m_errorsReport;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnSyntaxHelp( wxHyperlinkEvent& event ) { event.Skip(); }
|
||||
virtual void OnCompile( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnErrorLinkClicked( wxHtmlLinkEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#include <drc/drc_textvar_tester.h>
|
||||
#include <drc/footprint_tester.h>
|
||||
#include <dialogs/panel_setup_rules.h>
|
||||
|
||||
#include <reporter.h>
|
||||
|
||||
DRC::DRC() :
|
||||
PCB_TOOL_BASE( "pcbnew.DRCTool" ),
|
||||
|
@ -196,7 +196,7 @@ bool DRC::LoadRules()
|
|||
try
|
||||
{
|
||||
DRC_RULES_PARSER parser( m_pcb, fp, rulesFilepath );
|
||||
parser.Parse( m_rules );
|
||||
parser.Parse( m_rules, &NULL_REPORTER::GetInstance() );
|
||||
}
|
||||
catch( PARSE_ERROR& pe )
|
||||
{
|
||||
|
|
|
@ -29,53 +29,6 @@
|
|||
#include <pcb_expr_evaluator.h>
|
||||
|
||||
|
||||
/*
|
||||
* Rule tokens:
|
||||
* disallow
|
||||
* constraint
|
||||
* condition
|
||||
*
|
||||
* Disallow types:
|
||||
* track
|
||||
* via
|
||||
* micro_via
|
||||
* blind_via
|
||||
* pad
|
||||
* zone
|
||||
* text
|
||||
* graphic
|
||||
* hole
|
||||
*
|
||||
* Constraint types:
|
||||
* clearance
|
||||
* annulus_width
|
||||
* track_width
|
||||
* hole
|
||||
*
|
||||
*
|
||||
* (rule "HV"
|
||||
* (constraint clearance (min 200))
|
||||
* (condition "A.Netclass == 'HV' || B.Netclass == 'HV'")
|
||||
* )
|
||||
*
|
||||
* (rule "HV_external"
|
||||
* (constraint clearance (min 400))
|
||||
* (condition "(A.Netclass == 'HV' && (A.onLayer('F.Cu') || A.onLayer('B.Cu'))
|
||||
* || (B.Netclass == 'HV' && (B.onLayer('F.Cu') || B.onLayer('B.Cu'))")
|
||||
* )
|
||||
*
|
||||
* (rule "HV2HV" (constraint clearance (min 200)))
|
||||
* (rule "HV2HV_external" (constraint clearance (min 500)))
|
||||
* (rule "pad2padHV" (constraint clearance (min 500)))
|
||||
*
|
||||
* (rule "signal" (constraint clearance (min 20)))
|
||||
* (rule "neckdown" (constraint clearance (min 15)))
|
||||
*
|
||||
* (rule "disallowMicrovias" (disallow micro_via))
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint )
|
||||
{
|
||||
BOARD* board = aItem->GetBoard();
|
||||
|
@ -131,9 +84,9 @@ bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM
|
|||
}
|
||||
|
||||
|
||||
bool DRC_RULE_CONDITION::Compile()
|
||||
bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
|
||||
{
|
||||
PCB_EXPR_COMPILER compiler;
|
||||
PCB_EXPR_COMPILER compiler( aReporter, aSourceLine, aSourceOffset );
|
||||
|
||||
if (!m_ucode)
|
||||
m_ucode = new PCB_EXPR_UCODE;
|
||||
|
@ -145,13 +98,7 @@ bool DRC_RULE_CONDITION::Compile()
|
|||
if( ok )
|
||||
return true;
|
||||
|
||||
m_compileError = compiler.GetErrorStatus();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
LIBEVAL::ERROR_STATUS DRC_RULE_CONDITION::GetCompilationError()
|
||||
{
|
||||
return m_compileError;
|
||||
}
|
||||
|
|
|
@ -85,8 +85,7 @@ public:
|
|||
~DRC_RULE_CONDITION();
|
||||
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
|
||||
bool Compile();
|
||||
LIBEVAL::ERROR_STATUS GetCompilationError();
|
||||
bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
||||
|
||||
public:
|
||||
LSET m_LayerCondition;
|
||||
|
@ -94,7 +93,6 @@ public:
|
|||
wxString m_TargetRuleName;
|
||||
|
||||
private:
|
||||
LIBEVAL::ERROR_STATUS m_compileError;
|
||||
PCB_EXPR_UCODE* m_ucode;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <drc/drc_rule_parser.h>
|
||||
#include <drc_rules_lexer.h>
|
||||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
|
||||
#include <drc/drc_rule_parser.h>
|
||||
#include <drc_rules_lexer.h>
|
||||
#include <pcb_expr_evaluator.h>
|
||||
#include <reporter.h>
|
||||
|
||||
using namespace DRCRULE_T;
|
||||
|
||||
|
@ -37,7 +39,8 @@ DRC_RULES_PARSER::DRC_RULES_PARSER( BOARD* aBoard, const wxString& aSource,
|
|||
DRC_RULES_LEXER( aSource.ToStdString(), aSourceDescr ),
|
||||
m_board( aBoard ),
|
||||
m_requiredVersion( 0 ),
|
||||
m_tooRecent( false )
|
||||
m_tooRecent( false ),
|
||||
m_reporter( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -46,33 +49,95 @@ DRC_RULES_PARSER::DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxString&
|
|||
DRC_RULES_LEXER( aFile, aFilename ),
|
||||
m_board( aBoard ),
|
||||
m_requiredVersion( 0 ),
|
||||
m_tooRecent( false )
|
||||
m_tooRecent( false ),
|
||||
m_reporter( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DRC_RULES_PARSER::Parse( std::vector<DRC_RULE*>& aRules )
|
||||
void DRC_RULES_PARSER::reportError( const wxString& aMessage )
|
||||
{
|
||||
wxString rest;
|
||||
wxString first = aMessage.BeforeFirst( '|', &rest );
|
||||
wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
|
||||
CurLineNumber(),
|
||||
CurOffset(),
|
||||
first,
|
||||
rest );
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
|
||||
void DRC_RULES_PARSER::parseUnknown()
|
||||
{
|
||||
int depth = 1;
|
||||
|
||||
for( T token = NextTok(); token != T_EOF; token = NextTok() )
|
||||
{
|
||||
if( token == T_LEFT )
|
||||
depth++;
|
||||
|
||||
if( token == T_RIGHT )
|
||||
{
|
||||
if( --depth == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_RULES_PARSER::Parse( std::vector<DRC_RULE*>& aRules, REPORTER* aReporter )
|
||||
{
|
||||
bool haveVersion = false;
|
||||
wxString msg;
|
||||
|
||||
m_reporter = aReporter;
|
||||
|
||||
for( T token = NextTok(); token != T_EOF; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
if( !haveVersion && token != T_version )
|
||||
Expecting( "version" );
|
||||
{
|
||||
reportError( _( "Missing version statement." ) );
|
||||
haveVersion = true; // don't keep on reporting it
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_version:
|
||||
NeedNUMBER( "version" );
|
||||
haveVersion = true;
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing version number." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( (int) token == DSN_NUMBER )
|
||||
{
|
||||
m_requiredVersion = (int)strtol( CurText(), NULL, 10 );
|
||||
m_tooRecent = ( m_requiredVersion > DRC_RULE_FILE_VERSION );
|
||||
haveVersion = true;
|
||||
NeedRIGHT();
|
||||
token = NextTok();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected version number" ), FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
if( (int) token != DSN_RIGHT )
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'." ), FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_rule:
|
||||
|
@ -80,9 +145,13 @@ void DRC_RULES_PARSER::Parse( std::vector<DRC_RULE*>& aRules )
|
|||
break;
|
||||
|
||||
default:
|
||||
Expecting( "rule" );
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'rule' or 'version'." ), FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
m_reporter = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,23 +159,33 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
{
|
||||
DRC_RULE* rule = new DRC_RULE();
|
||||
T token = NextTok();
|
||||
wxString msg;
|
||||
|
||||
if( !IsSymbol( token ) )
|
||||
Expecting( "rule name" );
|
||||
reportError( _( "Missing rule name." ) );
|
||||
|
||||
rule->m_Name = FromUTF8();
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_disallow:
|
||||
switch( NextTok() )
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing disallowed type.| Expected 'track', 'via', 'micro_via', "
|
||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_track: rule->m_DisallowFlags |= DISALLOW_TRACKS; break;
|
||||
case T_via: rule->m_DisallowFlags |= DISALLOW_VIAS; break;
|
||||
|
@ -118,12 +197,21 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
case T_graphic: rule->m_DisallowFlags |= DISALLOW_GRAPHICS; break;
|
||||
case T_hole: rule->m_DisallowFlags |= DISALLOW_HOLES; break;
|
||||
case T_footprint: rule->m_DisallowFlags |= DISALLOW_FOOTPRINTS; break;
|
||||
default: Expecting( "track, via, micro_via, blind_via, pad, zone, text, "
|
||||
"graphic, or hole" );
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'track', 'via', 'micro_via', "
|
||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
rule->m_ConstraintFlags = DISALLOW_CONSTRAINT;
|
||||
NeedRIGHT();
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_constraint:
|
||||
|
@ -131,17 +219,32 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
break;
|
||||
|
||||
case T_condition:
|
||||
NeedSYMBOL();
|
||||
rule->m_Condition.m_Expression = FromUTF8();
|
||||
token = NextTok();
|
||||
|
||||
if( !rule->m_Condition.Compile() )
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
LIBEVAL::ERROR_STATUS error = rule->m_Condition.GetCompilationError();
|
||||
THROW_PARSE_ERROR( error.message, CurSource(), CurLine(), CurLineNumber(),
|
||||
CurOffset() + error.srcPos );
|
||||
reportError( _( "Missing condition expression." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( IsSymbol( token ) )
|
||||
{
|
||||
rule->m_Condition.m_Expression = FromUTF8();
|
||||
rule->m_Condition.Compile( m_reporter, CurLineNumber(), CurOffset() );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected quoted expression." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_layer:
|
||||
|
@ -149,7 +252,11 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
break;
|
||||
|
||||
default:
|
||||
Expecting( "disallow, constraint or condition" );
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'constraint', 'condition' or "
|
||||
"'disallow'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,16 +267,30 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
|||
void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
{
|
||||
T token;
|
||||
int constraintType;
|
||||
int constraintType = 0;
|
||||
int value;
|
||||
wxString msg;
|
||||
|
||||
switch( NextTok() )
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing constraint type.| Expected 'clearance', 'track_width', "
|
||||
"'annulus_width' or 'hole'." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_clearance: constraintType = CLEARANCE_CONSTRAINT; break;
|
||||
case T_track_width: constraintType = TRACK_CONSTRAINT; break;
|
||||
case T_annulus_width: constraintType = ANNULUS_CONSTRAINT; break;
|
||||
case T_hole: constraintType = HOLE_CONSTRAINT; break;
|
||||
default: Expecting( "clearance, track_width, annulus_width, or hole" ); return;
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'clearance', 'track_width', "
|
||||
"'annulus_width' or 'hole'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
aRule->m_ConstraintFlags |= constraintType;
|
||||
|
@ -177,14 +298,21 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
|||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_min:
|
||||
NextTok();
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing min value." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
|
||||
switch( constraintType )
|
||||
|
@ -195,39 +323,69 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
|||
case HOLE_CONSTRAINT: aRule->m_MinHole = value; break;
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_max:
|
||||
NextTok();
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing max value." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
|
||||
switch( constraintType )
|
||||
{
|
||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Max = value; break;
|
||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Max = value; break;
|
||||
default: Expecting( "min" );
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_opt:
|
||||
NextTok();
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing opt value." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
|
||||
switch( constraintType )
|
||||
{
|
||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Opt = value; break;
|
||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Opt = value; break;
|
||||
default: Expecting( "min" );
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
Expecting( "allow or constraint" );
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'min', 'max' or 'opt'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -235,17 +393,9 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
|||
|
||||
void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult )
|
||||
{
|
||||
PCB_EXPR_EVALUATOR evaluator;
|
||||
|
||||
bool ok = evaluator.Evaluate( aExpr );
|
||||
|
||||
if( !ok )
|
||||
{
|
||||
LIBEVAL::ERROR_STATUS error = evaluator.GetErrorStatus();
|
||||
THROW_PARSE_ERROR( error.message, CurSource(), CurLine(), CurLineNumber(),
|
||||
CurOffset() + error.srcPos );
|
||||
}
|
||||
PCB_EXPR_EVALUATOR evaluator( m_reporter, CurLineNumber(), CurOffset() );
|
||||
|
||||
evaluator.Evaluate( aExpr );
|
||||
aResult = evaluator.Result();
|
||||
}
|
||||
|
||||
|
@ -253,13 +403,18 @@ void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult
|
|||
LSET DRC_RULES_PARSER::parseLayer()
|
||||
{
|
||||
LSET retVal;
|
||||
int tok = NextTok();
|
||||
int token = NextTok();
|
||||
|
||||
if( tok == T_outer )
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing layer name or type." ) );
|
||||
return LSET::AllCuMask();
|
||||
}
|
||||
else if( token == T_outer )
|
||||
{
|
||||
retVal = LSET::ExternalCuMask();
|
||||
}
|
||||
else if( tok == T_inner )
|
||||
else if( token == T_inner )
|
||||
{
|
||||
retVal = LSET::InternalCuMask();
|
||||
}
|
||||
|
@ -269,14 +424,16 @@ LSET DRC_RULES_PARSER::parseLayer()
|
|||
PCB_LAYER_ID layer = ENUM_MAP<PCB_LAYER_ID>::Instance().ToEnum( layerName );
|
||||
|
||||
if( layer == UNDEFINED_LAYER )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Unrecognized layer '%s' " ), layerName );
|
||||
THROW_PARSE_ERROR( msg, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
|
||||
}
|
||||
reportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) );
|
||||
|
||||
retVal.set( layer );
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
DRC_RULES_PARSER( BOARD* aBoard, const wxString& aSource, const wxString& aSourceDescr );
|
||||
DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxString& aFilename );
|
||||
|
||||
void Parse( std::vector<DRC_RULE*>& aRules );
|
||||
void Parse( std::vector<DRC_RULE*>& aRules, REPORTER* aReporter );
|
||||
|
||||
private:
|
||||
DRC_RULE* parseDRC_RULE();
|
||||
|
@ -51,11 +51,15 @@ private:
|
|||
void parseConstraint( DRC_RULE* aRule );
|
||||
void parseValueWithUnits( const wxString& aExpr, int& aResult );
|
||||
LSET parseLayer();
|
||||
void parseUnknown();
|
||||
|
||||
void reportError( const wxString& aMessage );
|
||||
|
||||
private:
|
||||
BOARD* m_board;
|
||||
int m_requiredVersion;
|
||||
bool m_tooRecent;
|
||||
REPORTER* m_reporter;
|
||||
};
|
||||
|
||||
#endif // DRC_RULE_PARSER_H
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include <cstdio>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <memory>
|
||||
#include "class_board.h"
|
||||
#include "pcb_expr_evaluator.h"
|
||||
|
||||
#include <reporter.h>
|
||||
#include <class_board.h>
|
||||
#include <pcb_expr_evaluator.h>
|
||||
|
||||
|
||||
static void onLayer( LIBEVAL::CONTEXT* aCtx, void *self )
|
||||
|
@ -187,8 +187,7 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
|||
}
|
||||
|
||||
|
||||
LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::createFuncCall( LIBEVAL::COMPILER* aCompiler,
|
||||
const char* aName )
|
||||
LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::CreateFuncCall( const char* aName )
|
||||
{
|
||||
PCB_EXPR_BUILTIN_FUNCTIONS& registry = PCB_EXPR_BUILTIN_FUNCTIONS::Instance();
|
||||
|
||||
|
@ -199,8 +198,7 @@ LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::createFuncCall( LIBEVAL::COMPILER* aCom
|
|||
}
|
||||
|
||||
|
||||
LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler, const char* aVar,
|
||||
const char* aField )
|
||||
LIBEVAL::VAR_REF* PCB_EXPR_UCODE::CreateVarRef( const char* aVar, const char* aField )
|
||||
{
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
PCB_EXPR_VAR_REF* vref = nullptr;
|
||||
|
@ -215,7 +213,6 @@ LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler, co
|
|||
}
|
||||
else
|
||||
{
|
||||
aCompiler->ReportError( "var" );
|
||||
return vref;
|
||||
}
|
||||
|
||||
|
@ -251,16 +248,14 @@ LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler, co
|
|||
}
|
||||
else
|
||||
{
|
||||
(void) 0; // should we do anything here?
|
||||
//msg.Printf("Unrecognized type for property '%s'", field.c_str() );
|
||||
//aCompiler->ReportError( (const char*) msg.c_str() );
|
||||
wxFAIL_MSG( "PCB_EXPR_UCODE::createVarRef: Unknown property type." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( vref->GetType() == LIBEVAL::VT_UNDEFINED )
|
||||
aCompiler->ReportError( "field" );
|
||||
vref->SetType( LIBEVAL::VT_PARSE_ERROR );
|
||||
|
||||
return vref;
|
||||
}
|
||||
|
@ -295,13 +290,15 @@ public:
|
|||
};
|
||||
|
||||
|
||||
PCB_EXPR_COMPILER::PCB_EXPR_COMPILER()
|
||||
PCB_EXPR_COMPILER::PCB_EXPR_COMPILER( REPORTER* aReporter, int aSourceLine, int aSourcePos ) :
|
||||
COMPILER( aReporter, aSourceLine, aSourcePos )
|
||||
{
|
||||
m_unitResolver = std::make_unique<PCB_UNIT_RESOLVER>();
|
||||
}
|
||||
|
||||
|
||||
PCB_EXPR_EVALUATOR::PCB_EXPR_EVALUATOR()
|
||||
PCB_EXPR_EVALUATOR::PCB_EXPR_EVALUATOR( REPORTER* aReporter, int aSourceLine, int aSourceOffset ) :
|
||||
m_compiler( aReporter, aSourceLine, aSourceOffset )
|
||||
{
|
||||
m_result = 0;
|
||||
}
|
||||
|
@ -316,15 +313,10 @@ bool PCB_EXPR_EVALUATOR::Evaluate( const wxString& aExpr )
|
|||
PCB_EXPR_UCODE ucode;
|
||||
LIBEVAL::CONTEXT preflightContext;
|
||||
|
||||
if( !m_compiler.Compile( aExpr.ToUTF8().data(), &ucode, &preflightContext ) )
|
||||
{
|
||||
m_errorStatus = m_compiler.GetErrorStatus();
|
||||
return false;
|
||||
}
|
||||
m_compiler.Compile( aExpr.ToUTF8().data(), &ucode, &preflightContext );
|
||||
|
||||
// fixme: handle error conditions
|
||||
LIBEVAL::CONTEXT ctx;
|
||||
LIBEVAL::VALUE* result = ucode.Run( &ctx );
|
||||
LIBEVAL::CONTEXT evaluationContext;
|
||||
LIBEVAL::VALUE* result = ucode.Run( &evaluationContext );
|
||||
|
||||
if( result->GetType() == LIBEVAL::VT_NUMERIC )
|
||||
m_result = KiROUND( result->AsDouble() );
|
||||
|
|
|
@ -43,10 +43,9 @@ public:
|
|||
PCB_EXPR_UCODE() {};
|
||||
virtual ~PCB_EXPR_UCODE() {};
|
||||
|
||||
virtual LIBEVAL::VAR_REF* createVarRef( LIBEVAL::COMPILER *aCompiler, const char* aVar,
|
||||
const char* aField ) override;
|
||||
virtual LIBEVAL::VAR_REF* CreateVarRef( const char* aVar, const char* aField ) override;
|
||||
|
||||
virtual FUNC_PTR createFuncCall( LIBEVAL::COMPILER* aCompiler, const char* aName ) override;
|
||||
virtual FUNC_PTR CreateFuncCall( const char* aName ) override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -83,7 +82,7 @@ public:
|
|||
m_type( LIBEVAL::VT_UNDEFINED ),
|
||||
m_isEnum( false )
|
||||
{
|
||||
//printf("*** createVarRef %p %d\n", this, aItemIndex );
|
||||
//printf("*** CreateVarRef %p %d\n", this, aItemIndex );
|
||||
}
|
||||
|
||||
void SetIsEnum( bool s ) { m_isEnum = s; }
|
||||
|
@ -142,28 +141,24 @@ private:
|
|||
class PCB_EXPR_COMPILER : public LIBEVAL::COMPILER
|
||||
{
|
||||
public:
|
||||
PCB_EXPR_COMPILER();
|
||||
PCB_EXPR_COMPILER( REPORTER* aReporter, int aSourceLine, int aSourcePos );
|
||||
};
|
||||
|
||||
|
||||
class PCB_EXPR_EVALUATOR
|
||||
{
|
||||
public:
|
||||
PCB_EXPR_EVALUATOR();
|
||||
PCB_EXPR_EVALUATOR( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
||||
~PCB_EXPR_EVALUATOR();
|
||||
|
||||
bool Evaluate( const wxString& aExpr );
|
||||
int Result() const { return m_result; }
|
||||
|
||||
LIBEVAL::ERROR_STATUS GetErrorStatus() { return m_errorStatus; }
|
||||
|
||||
private:
|
||||
int m_result;
|
||||
|
||||
PCB_EXPR_COMPILER m_compiler;
|
||||
PCB_EXPR_UCODE m_ucode;
|
||||
|
||||
LIBEVAL::ERROR_STATUS m_errorStatus;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,7 +78,7 @@ bool test::DRC_ENGINE::LoadRules( wxFileName aPath )
|
|||
try
|
||||
{
|
||||
DRC_RULES_PARSER parser( m_board, fp, aPath.GetFullPath() );
|
||||
parser.Parse( m_ruleConditions, m_rules );
|
||||
parser.Parse( m_ruleConditions, m_rules, &NULL_REPORTER::GetInstance() );
|
||||
}
|
||||
catch( PARSE_ERROR& pe )
|
||||
{
|
||||
|
@ -175,7 +175,7 @@ bool test::DRC_ENGINE::CompileRules()
|
|||
{
|
||||
rcons->conditions.push_back( condition );
|
||||
|
||||
bool compileOk = condition->Compile();
|
||||
bool compileOk = condition->Compile( &NULL_REPORTER::GetInstance() );
|
||||
|
||||
ReportAux( wxString::Format( " |- condition: '%s' compile: %s", condition->m_TargetRuleName, compileOk ? "OK" : "ERROR") );
|
||||
|
||||
|
|
|
@ -64,9 +64,9 @@ bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOAR
|
|||
}
|
||||
|
||||
|
||||
bool test::DRC_RULE_CONDITION::Compile()
|
||||
bool test::DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
|
||||
{
|
||||
PCB_EXPR_COMPILER compiler;
|
||||
PCB_EXPR_COMPILER compiler( aReporter, aSourceLine, aSourceOffset );
|
||||
|
||||
if (!m_ucode)
|
||||
m_ucode = new PCB_EXPR_UCODE;
|
||||
|
@ -74,19 +74,7 @@ bool test::DRC_RULE_CONDITION::Compile()
|
|||
LIBEVAL::CONTEXT preflightContext;
|
||||
|
||||
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
||||
|
||||
if( ok )
|
||||
return true;
|
||||
|
||||
m_compileError = compiler.GetErrorStatus();
|
||||
|
||||
printf( "Fail: %s (pos: %d)\n", (const char *) m_compileError.message.c_str(), m_compileError.srcPos );
|
||||
|
||||
return false;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
LIBEVAL::ERROR_STATUS test::DRC_RULE_CONDITION::GetCompilationError()
|
||||
{
|
||||
return m_compileError;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ public:
|
|||
DRC_CONSTRAINT m_Constraint;
|
||||
};
|
||||
|
||||
|
||||
class DRC_RULE_CONDITION
|
||||
{
|
||||
public:
|
||||
|
@ -132,15 +133,14 @@ public:
|
|||
~DRC_RULE_CONDITION();
|
||||
|
||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
|
||||
bool Compile();
|
||||
LIBEVAL::ERROR_STATUS GetCompilationError();
|
||||
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
|
||||
|
||||
public:
|
||||
LSET m_LayerCondition;
|
||||
wxString m_Expression;
|
||||
wxString m_TargetRuleName;
|
||||
|
||||
private:
|
||||
LIBEVAL::ERROR_STATUS m_compileError;
|
||||
PCB_EXPR_UCODE* m_ucode;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
|
||||
|
@ -29,11 +30,8 @@
|
|||
#include <drc_proto/drc_rule_parser.h>
|
||||
#include <drc_proto/drc_rules_lexer.h>
|
||||
#include <drc_proto/drc_engine.h> // drc_dbg
|
||||
|
||||
|
||||
#include <fctsys.h>
|
||||
|
||||
#include <pcb_expr_evaluator.h>
|
||||
#include <reporter.h>
|
||||
|
||||
using namespace DRCRULEPROTO_T;
|
||||
|
||||
|
@ -43,37 +41,94 @@ test::DRC_RULES_PARSER::DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxSt
|
|||
m_requiredVersion( 0 ),
|
||||
m_tooRecent( false )
|
||||
{
|
||||
for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
|
||||
}
|
||||
|
||||
|
||||
void test::DRC_RULES_PARSER::reportError( const wxString& aMessage )
|
||||
{
|
||||
std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) );
|
||||
m_layerMap[untranslated] = PCB_LAYER_ID( layer );
|
||||
wxString rest;
|
||||
wxString first = aMessage.BeforeFirst( '|', &rest );
|
||||
wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
|
||||
CurLineNumber(),
|
||||
CurOffset(),
|
||||
first,
|
||||
rest );
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
|
||||
void test::DRC_RULES_PARSER::parseUnknown()
|
||||
{
|
||||
int depth = 1;
|
||||
|
||||
for( T token = NextTok(); token != T_EOF; token = NextTok() )
|
||||
{
|
||||
if( token == T_LEFT )
|
||||
depth++;
|
||||
|
||||
if( token == T_RIGHT )
|
||||
{
|
||||
if( --depth == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test::DRC_RULES_PARSER::Parse(
|
||||
std::vector<test::DRC_RULE_CONDITION*>& aConditions, std::vector<test::DRC_RULE*>& aRules )
|
||||
void test::DRC_RULES_PARSER::Parse( std::vector<test::DRC_RULE_CONDITION*>& aConditions,
|
||||
std::vector<test::DRC_RULE*>& aRules,
|
||||
REPORTER* aReporter )
|
||||
{
|
||||
bool haveVersion = false;
|
||||
wxString msg;
|
||||
|
||||
m_reporter = aReporter;
|
||||
|
||||
for( T token = NextTok(); token != T_EOF; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
if( !haveVersion && token != T_version )
|
||||
Expecting( "version" );
|
||||
{
|
||||
reportError( _( "Missing version statement." ) );
|
||||
haveVersion = true; // don't keep on reporting it
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_version:
|
||||
NeedNUMBER( "version" );
|
||||
haveVersion = true;
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing version number." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( (int) token == DSN_NUMBER )
|
||||
{
|
||||
m_requiredVersion = (int)strtol( CurText(), NULL, 10 );
|
||||
m_tooRecent = ( m_requiredVersion > DRC_RULE_FILE_VERSION );
|
||||
haveVersion = true;
|
||||
NeedRIGHT();
|
||||
token = NextTok();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected version number" ), FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
if( (int) token != DSN_RIGHT )
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'." ), FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_condition:
|
||||
|
@ -89,7 +144,10 @@ void test::DRC_RULES_PARSER::Parse(
|
|||
}
|
||||
|
||||
default:
|
||||
Expecting( "condition or rule" );
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'rule', 'condition' or 'version'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +167,8 @@ test::DRC_RULE_CONDITION* test::DRC_RULES_PARSER::parseCONDITION()
|
|||
|
||||
//printf( "Do token xxx %d '%s'\n", token, (const char*) FromUTF8().c_str() );
|
||||
|
||||
// TODO: Needs updating to report errors through REPORTER
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_expression:
|
||||
|
@ -139,16 +199,17 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
|
|||
DRC_RULE* rule = new DRC_RULE();
|
||||
T token = NextTok();
|
||||
int value;
|
||||
wxString msg;
|
||||
|
||||
if( !IsSymbol( token ) )
|
||||
Expecting( "rule name" );
|
||||
reportError( _( "Missing rule name." ) );
|
||||
|
||||
rule->m_Name = FromUTF8();
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
|
@ -157,26 +218,70 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
|
|||
switch( token )
|
||||
{
|
||||
case T_type:
|
||||
// TODO: I assume this won't be in the final impl and so doesn't need converting
|
||||
// to new error reporting framework?
|
||||
NeedSYMBOL();
|
||||
rule->m_TestProviderName = FromUTF8();
|
||||
break;
|
||||
|
||||
case T_min:
|
||||
NeedSYMBOL();
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing min value." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
rule->m_Constraint.m_Value.SetMin( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_opt:
|
||||
NeedSYMBOL();
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing opt value." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
rule->m_Constraint.m_Value.SetOpt( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_max:
|
||||
NeedSYMBOL();
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing max value." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
rule->m_Constraint.m_Value.SetMax( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_allow:
|
||||
|
@ -209,7 +314,12 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
|
|||
|
||||
|
||||
default:
|
||||
Expecting( "type, min, opt, max, allow, enable, priority or severity" );
|
||||
// TODO: reconcile
|
||||
//Expecting( "type, min, opt, max, allow, enable, priority or severity" );
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'min', 'max' or 'opt'." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -222,16 +332,47 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
|
|||
|
||||
void test::DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult )
|
||||
{
|
||||
PCB_EXPR_EVALUATOR evaluator;
|
||||
|
||||
bool ok = evaluator.Evaluate( aExpr );
|
||||
|
||||
if( !ok )
|
||||
{
|
||||
LIBEVAL::ERROR_STATUS error = evaluator.GetErrorStatus();
|
||||
THROW_PARSE_ERROR( error.message, CurSource(), CurLine(), CurLineNumber(),
|
||||
CurOffset() + error.srcPos );
|
||||
}
|
||||
PCB_EXPR_EVALUATOR evaluator( m_reporter, CurLineNumber(), CurOffset() );
|
||||
|
||||
evaluator.Evaluate( aExpr );
|
||||
aResult = evaluator.Result();
|
||||
};
|
||||
|
||||
|
||||
LSET test::DRC_RULES_PARSER::parseLayer()
|
||||
{
|
||||
LSET retVal;
|
||||
int token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing layer name or type." ) );
|
||||
return LSET::AllCuMask();
|
||||
}
|
||||
else if( token == T_outer )
|
||||
{
|
||||
retVal = LSET::ExternalCuMask();
|
||||
}
|
||||
else if( token == T_inner )
|
||||
{
|
||||
retVal = LSET::InternalCuMask();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString layerName = FromUTF8();
|
||||
PCB_LAYER_ID layer = ENUM_MAP<PCB_LAYER_ID>::Instance().ToEnum( layerName );
|
||||
|
||||
if( layer == UNDEFINED_LAYER )
|
||||
reportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) );
|
||||
|
||||
retVal.set( layer );
|
||||
}
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ class DRC_RULES_PARSER : public DRC_RULES_PROTO_LEXER
|
|||
public:
|
||||
DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxString& aFilename );
|
||||
|
||||
void Parse( std::vector<DRC_RULE_CONDITION*>& aConditions, std::vector<DRC_RULE*>& aRules );
|
||||
void Parse( std::vector<DRC_RULE_CONDITION*>& aConditions, std::vector<DRC_RULE*>& aRules,
|
||||
REPORTER* aReporter );
|
||||
|
||||
private:
|
||||
DRC_RULE_CONDITION* parseCONDITION();
|
||||
|
@ -63,6 +64,11 @@ private:
|
|||
return parseInt();
|
||||
}
|
||||
|
||||
LSET parseLayer();
|
||||
void parseUnknown();
|
||||
|
||||
void reportError( const wxString& aMessage );
|
||||
|
||||
// void parseConstraint( DRC_RULE* aRule );
|
||||
//int parseValue( DRCRULE_T::T aToken );
|
||||
|
||||
|
@ -71,8 +77,7 @@ private:
|
|||
BOARD* m_board;
|
||||
int m_requiredVersion;
|
||||
bool m_tooRecent;
|
||||
|
||||
std::unordered_map<std::string, PCB_LAYER_ID> m_layerMap;
|
||||
REPORTER* m_reporter;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
clearance
|
||||
condition
|
||||
constraint
|
||||
inner
|
||||
layer
|
||||
max
|
||||
min
|
||||
name
|
||||
opt
|
||||
outer
|
||||
allow
|
||||
rule
|
||||
version
|
||||
name
|
||||
priority
|
||||
expression
|
||||
enable
|
||||
|
|
Loading…
Reference in New Issue