SolidCode / SolidPython

A python frontend for solid modelling that compiles to OpenSCAD
1.11k stars 173 forks source link

Modul's arguments parsing error #95

Closed Torlos closed 5 years ago

Torlos commented 5 years ago

Hello,

When I "use" Chamfers-for-OpenSCAD, this error is raised :

.../lib/python3.6/site-packages/solid/objects.py", line 643, in use
    exec(class_str, calling_module(stack_depth).__dict__)
  File "<string>", line 3
    def __init__(self, chamferHeight2, 1, **kwargs):

The scad modul code :

    module box(brim = abs(min(chamferHeight2, 0)) + 1) {
        translate([-radius - brim, 0, -brim]) cube([radius * 2 + brim * 2, radius + brim, height + brim * 2]);
    }

The generated python code is :

import solid
class box(solid.IncludedOpenSCADObject):
   def __init__(self, chamferHeight2, 1, **kwargs):
       solid.IncludedOpenSCADObject.__init__(self, 'box', {'chamferHeight2':chamferHeight2, '1':1,  }, include_file_path='/home/smaza/Documents/Privé_et_Personnel/azami-cal/Ring/V2/lib/Chamfers-for-OpenSCAD/Chamfer.scad', use_not_include=True, **kwargs )

I propose this modification like this :

diff --git i/solid/solidpython.py w/solid/solidpython.py
index ff96e34..ee7ea46 100755
--- i/solid/solidpython.py
+++ w/solid/solidpython.py
@@ -195,7 +195,7 @@ def parse_scad_callables(scad_code_str):
     # This is brittle.  To get a generally applicable expression for all arguments,
     # we'd need a real parser to handle nested-list default args or parenthesized statements.
     # For the moment, assume a maximum of one square-bracket-delimited list
-    args_re = r'(?mxs)(?P<arg_name>\w+)(?:\s*=\s*(?P<default_val>[\w.-]+|\[.*\]))?(?:,|$)'
+    args_re = r'(?mxs)(?P<arg_name>\w+)(?:\s*=\s*(?P<default_val>[\w()\,\s+-\/*.]+|\[.*\]))?(?:,|$)'

     # remove all comments from SCAD code
     scad_code_str = re.sub(no_comments_re, '', scad_code_str)

Torlos

etjones commented 5 years ago

Ugh. module box(brim = abs(min(chamferHeight2, 0)) + 1) is a really ugly method signature. I don't know how I feel about supporting that kind of extra complexity in a signature.

But... as currently written, you're right that SolidPython will definitely crash on that one.

Without spending a while running through the regex, I'm not sure what your edit does. Can you describe what you're accomplishing, and give some examples of strings that would match the regex and which would not? Or even better, insert comments in the regex?

Torlos commented 5 years ago

Thank you for your attention.

I have update my regular expression for more cases of use. But for recursion parsing and and balanced brackets I use the python module regex (pip install regex) which is more complete. So in file solidpython.py :

import regex as re

You cas see the difference between old ann nex regular expression

With

(?mxs)(?P<arg_name>\w+)(?:\s*=\s*(?P<default_val>[\w.-]+|\[.*\]))?(?:,|$)

Only expressions 1 to 9 matched

var5,
var2=78,
var_true = true,
var_true = false,
var_int = 5,
var_negative = -5,
var_float = 5.5,
var_number = -5e89,
var_empty_vector = [],
var_simple_string = "simple string",
var_complexe_string = "a \"complexe\"\tstring with a\\",
var_vector = [5454445, 565, [44545]],
var_complexe_vector = [545 + 4445, 565, [cos(75) + len("yes", 45)]],
var_vector = [5, 6, "string\twith\ttab"],
var_range = [0:10e10],
var_range_step = [-10:0.5:10],
var_with_arithmetic = 8 * 9 - 1 + 89 / 15,
var_with_parentheses = 8 * ((9 - 1) + 89) / 15,
var_with_functions = abs(min(chamferHeight2, 0)) */-+ 1,
var_with_conditionnal_assignement = mytest ? 45 : yop,

with

(?mxs)(?P<arg_name>\w+)(?:\s*=\s*(?P<default_val>([\w.\"\s\?:\-+\\\/*]+|\((?>[^()]|(?2))*\)|\[(?>[^\[\]]|(?2))*\])+))?(?:,|$)

all expressions matched

PS: I agree with you, it's a really ugly method signature.

etjones commented 5 years ago

That's a really great set of examples, Torlos. Thanks for putting those together. I'm incorporating the change and the extra dependency and I'll make a new release in the next few days when that's all done. Cheers!