From 466cbe2f000ed82d31f3a57a5fa0ae8014e1dc19 Mon Sep 17 00:00:00 2001
From: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
Date: Thu, 27 Aug 2020 00:00:42 +0200
Subject: [PATCH] libeval_compiler: fixhandling of method calls with empty
 argument list (e.g. 'A.method()' )

---
 common/libeval_compiler/grammar.lemon        | 7 +++++++
 common/libeval_compiler/libeval_compiler.cpp | 3 +++
 include/libeval_compiler/libeval_compiler.h  | 3 ++-
 qa/pcbnew/test_libeval_compiler.cpp          | 9 ++++++++-
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/common/libeval_compiler/grammar.lemon b/common/libeval_compiler/grammar.lemon
index fc14a9dc85..f551604b58 100644
--- a/common/libeval_compiler/grammar.lemon
+++ b/common/libeval_compiler/grammar.lemon
@@ -199,3 +199,10 @@ nt(A) ::= G_IDENTIFIER(F) G_PARENL nt(B) G_PARENR.
     A->leaf[0] = newNode( pEval, TR_IDENTIFIER, F.value);
     A->leaf[1] = B;
 }
+
+nt(A) ::= G_IDENTIFIER(F) G_PARENL G_PARENR.
+{
+    A = newNode( pEval, TR_OP_FUNC_CALL );
+    A->leaf[0] = newNode( pEval, TR_IDENTIFIER, F.value);
+    A->leaf[1] = newNode( pEval, TR_NULL );
+}
\ No newline at end of file
diff --git a/common/libeval_compiler/libeval_compiler.cpp b/common/libeval_compiler/libeval_compiler.cpp
index 93d3e8cf40..f711c5b83d 100644
--- a/common/libeval_compiler/libeval_compiler.cpp
+++ b/common/libeval_compiler/libeval_compiler.cpp
@@ -542,6 +542,9 @@ void dumpNode( wxString& buf, TREE_NODE* tok, int depth = 0 )
 {
     wxString str;
 
+    if( !tok )
+        return;
+
     str.Printf( "\n[%p L0:%-20p L1:%-20p] ", tok, tok->leaf[0], tok->leaf[1] );
     buf += str;
 
diff --git a/include/libeval_compiler/libeval_compiler.h b/include/libeval_compiler/libeval_compiler.h
index c657c6783e..636eeeef3b 100644
--- a/include/libeval_compiler/libeval_compiler.h
+++ b/include/libeval_compiler/libeval_compiler.h
@@ -89,7 +89,8 @@ enum TOKEN_TYPE_T
     TR_ASSIGN     = 3,
     TR_STRUCT_REF = 4,
     TR_STRING     = 5,
-    TR_UNIT       = 6
+    TR_UNIT       = 6,
+    TR_NULL       = 7
 };
 
 class UOP;
diff --git a/qa/pcbnew/test_libeval_compiler.cpp b/qa/pcbnew/test_libeval_compiler.cpp
index 604c487e0b..378f63b082 100644
--- a/qa/pcbnew/test_libeval_compiler.cpp
+++ b/qa/pcbnew/test_libeval_compiler.cpp
@@ -78,7 +78,8 @@ const static std::vector<EXPR_TO_TEST> introspectionExpressions = {
     { "(A.Netclass == 'HV') && (B.netclass == 'otherClass') && (B.netclass != 'F.Cu')", false, VAL( 1.0 ) },
     { "A.Netclass + 1.0", false, VAL( 1.0 ) },
     { "A.type == 'Track' && B.type == 'Track' && A.layer == 'F.Cu'", false, VAL( 1.0 ) },
-    { "(A.type == 'Track') && (B.type == 'Track') && (A.layer == 'F.Cu')", false, VAL( 1.0 ) }
+    { "(A.type == 'Track') && (B.type == 'Track') && (A.layer == 'F.Cu')", false, VAL( 1.0 ) },
+    { "A.type == 'Via' && A.isMicroVia()", false, VAL(0.0) }
 };
 
 
@@ -92,12 +93,18 @@ static bool testEvalExpr( const wxString& expr, LIBEVAL::VALUE expectedResult,
 
     context.SetItems( itemA, itemB );
 
+
+    BOOST_TEST_MESSAGE("Expr: '" << expr.c_str() << "'");
+
     bool error = !compiler.Compile( expr, &ucode, &preflightContext );
 
     BOOST_CHECK_EQUAL( error, expectError );
 
     if( error != expectError )
     {
+        BOOST_TEST_MESSAGE( "Result: FAIL: " << compiler.GetError().message.c_str() <<
+                            " (code pos: " << compiler.GetError().srcPos << ")" );
+
         return false;
     }