1. boldport
  2. Untitled project
  3. PCBmodE

Commits

Saar Drimer  committed 54eed9c

parser and converting to dict for basic Gerber seems to be working

  • Participants
  • Parent commits 14a9dab
  • Branches production

Comments (0)

Files changed (1)

File utils/gerber.py

View file
 import utils
 from Point import Point
 
+from pprint import pprint
 
 
 def gerberise(cfg, manufacturer='default'):
    Returns the grammar of Gerber
    """
 
+   gerber_dictionary = {
+       "G04": { "text": "comment" },   
+       "G36": { "text": "closed-shape-start" }, 
+       "G37": { "text": "closed-shape-end" },
+
+       "MO": { "text": "units",
+               "MM": { "text": "mm" },
+               "IN": { "text": "inch" }
+             },
+
+       "AD": { "text": "aperture-definition",
+               "C": { "text": "circle" },
+               "R": { "text": "rectangle" }
+             },
+
+       "FS": { "text": "format" ,
+               "L": { "text": "leading-zeros" },
+               "A": { "text": "absolute" }
+             },
+       
+       "D01": { "text": "draw"},
+       "D02": { "text": "move"},
+       "D03": { "text": "flash"}
+
+   }
+
+
+
    # define grammar using pyparsing
    space = pyp.Literal(' ')
-   comma = pyp.Literal(',')
-   floatnum = pyp.Regex(r'([\d\.]+)')
-   apperture = pyp.Literal('D').setParseAction(pyp.replaceWith('apperture'))
+   comma = pyp.Literal(',').suppress()
+   #floatnum = pyp.Regex(r'([\d\.]+)')
+
+   # capture a float string and cast to float
+   floatnum = pyp.Regex(r'([\d\.]+)').setParseAction(lambda t: float(t[0]))
+
+   # capture integer string and cast to int
+   integer = pyp.Regex(r'(-?\d+)').setParseAction(lambda t: int(t[0]))
+
+   # capture single digit string and cast to int
+   single_digit = pyp.Regex(r'(\d)').setParseAction(lambda t: int(t[0]))
+
+   aperture = pyp.Literal('D').setParseAction(pyp.replaceWith('aperture'))
    coord_x = pyp.Literal('X').setParseAction(pyp.replaceWith('x'))
    coord_y = pyp.Literal('Y').setParseAction(pyp.replaceWith('y'))
    gcoord = pyp.Regex(r'(-?\d+)')
    cmd_closed_shape_end = pyp.Literal('G37')
    #cmd_closed_shape_end.setParseAction(pyp.replaceWith('close-shape'))
 
-   cmd_units = pyp.Literal('MO')
-   cmd_units_opt_mm = pyp.Literal('MM')
-   cmd_units_opt_inch = pyp.Literal('IN')
+   cmd_units = pyp.Literal('MO')('gerber-command')
+   cmd_units_opt_mm = pyp.Literal('MM').setParseAction(pyp.replaceWith('mm'))
+   cmd_units_opt_inch = pyp.Literal('IN').setParseAction(pyp.replaceWith('inch'))
 
-   cmd_format = pyp.Literal('FS')
-   cmd_format_opt_leading_zeros = pyp.Literal('L')
-   cmd_format_opt_absolute = pyp.Literal('A') 
+   cmd_format = pyp.Literal('FS')('gerber-command')
+   cmd_format_opt_leading_zeros = pyp.Literal('L').setParseAction(pyp.replaceWith('leading'))
+   cmd_format_opt_trailing_zeros = pyp.Literal('T').setParseAction(pyp.replaceWith('trailing'))
 
-   cmd_app_def = pyp.Literal('AD') # apperture definition
-   cmd_app_def_opt_circ = pyp.Literal('C')
-   cmd_app_def_opt_rect = pyp.Literal('R')
+   cmd_format_opt_absolute = pyp.Literal('A').setParseAction(pyp.replaceWith('absolute')) 
+   cmd_format_opt_incremental = pyp.Literal('I').setParseAction(pyp.replaceWith('incremental')) 
 
-   cmd_polarity = pyp.Literal('LP')
-   cmd_polarity_opt_dark = pyp.Literal('D')
-   cmd_polarity_opt_clear = pyp.Literal('C')
+   # aperture definition
+   cmd_ap_def = pyp.Literal('AD')('gerber-command')
+   cmd_ap_def_num = 'D' + integer.setResultsName('number')
+   cmd_ap_def_opt_circ = pyp.Literal('C').setParseAction(pyp.replaceWith('circle'))
+   cmd_ap_def_opt_rect = pyp.Literal('R').setParseAction(pyp.replaceWith('rect'))
+ 
+   cmd_polarity = pyp.Literal('LP')('gerber-command')
+   cmd_polarity_opt_dark = pyp.Literal('D').setParseAction(pyp.replaceWith('dark'))
+   cmd_polarity_opt_clear = pyp.Literal('C').setParseAction(pyp.replaceWith('clear'))
 
    cmd_linear_int = pyp.Literal('G01').suppress() # lineal interpolation
    cmd_circ_int_cw = pyp.Literal('G02').suppress() # circular int. clockwise
    cmd_circ_int_ccw = pyp.Literal('G03').suppress() # circular int. counter-clockwise
 
-   cmd_draw = pyp.Literal('D01').setParseAction(pyp.replaceWith('draw'))
-   cmd_move = pyp.Literal('D02').setParseAction(pyp.replaceWith('move'))
-   cmd_flash = pyp.Literal('D03').setParseAction(pyp.replaceWith('flash'))
+   #cmd_draw = pyp.Literal('D01').setParseAction(pyp.replaceWith(gerber_dictionary['D01']['text']))
+   #cmd_move = pyp.Literal('D02').setParseAction(pyp.replaceWith(gerber_dictionary['D02']['text']))
+   #cmd_flash = pyp.Literal('D03').setParseAction(pyp.replaceWith(gerber_dictionary['D03']['text']))
+
+   aperture_type = (((cmd_ap_def_opt_circ('type') + comma) + (floatnum)('diameter') + 'X') | 
+                    ((cmd_ap_def_opt_rect('type') + comma) + (floatnum)('width') + 'X' + (floatnum)('height'))) 
+
+   polarity_type = (cmd_polarity_opt_clear | cmd_polarity_opt_dark)('polarity')
+
+   units_type = (cmd_units_opt_mm | cmd_units_opt_inch)('units')
+
+   format_zeros = ((cmd_format_opt_leading_zeros('zeros')) |
+                   (cmd_format_opt_trailing_zeros('zeros')))
+
+   format_notation = ((cmd_format_opt_absolute('notation')) |
+                      (cmd_format_opt_incremental('notation')))
+
+   #xxx = pyp.Literal('X').setParseAction(pyp.replaceWith('x'))
+   #yyy = pyp.Literal('Y').setParseAction(pyp.replaceWith('y'))
+
+   format_data = (single_digit)('integer') + single_digit('decimal')
+
+   #format_data_xy = (xxx + format_data) + (yyy + format_data)
+   #format_data_y =  (single_digit)('integer') + single_digit('decimal')
+
 
    # comments (suppress)
    comment = (cmd_comment + 
               pyp.Optional(space) + 
               inst_end).suppress()
 
-   units = (inst_del + 
-            cmd_units + 
-            (cmd_units_opt_mm | cmd_units_opt_inch) + 
+   units = (inst_del +
+            pyp.Group(cmd_units +
+            units_type)('units') +  
             inst_end + 
             inst_del)
 
    gformat = (inst_del +
-              cmd_format +
-              cmd_format_opt_leading_zeros +
-              cmd_format_opt_absolute +
-              pyp.Literal('X') + 
-              floatnum +
-              pyp.Literal('Y') + 
-              floatnum +
+              pyp.Group(cmd_format +
+              format_zeros +
+              format_notation +
+              'X' + pyp.Group(format_data)('x') + 
+              'Y' + pyp.Group(format_data)('y'))('format') + 
               inst_end +
               inst_del)
 
-   app_def = (inst_del + 
-              cmd_app_def +
-              pyp.Literal('D') +
-              floatnum + 
-              (cmd_app_def_opt_circ | cmd_app_def_opt_rect) +
-              comma +
-              floatnum +
-              pyp.Literal('X') +
-              pyp.Optional(floatnum) + 
+   ap_def = (inst_del + 
+              pyp.Group(cmd_ap_def +
+              cmd_ap_def_num +
+              aperture_type)('aperture_definition') +
               inst_end +
-              inst_del)                            
+              inst_del)
 
    polarity = (inst_del +
-               cmd_polarity +
-               (cmd_polarity_opt_dark | cmd_polarity_opt_clear) +
+               pyp.Group(cmd_polarity +
+               polarity_type)('polarity_change') +
                inst_end +
-               inst_del)                            
+               inst_del)      
 
-   closed_shape_start = cmd_closed_shape_start + inst_end
-   closed_shape_end = cmd_closed_shape_end + inst_end
+   closed_shape_start = (cmd_closed_shape_start('start_closed_shape') + inst_end)
+   closed_shape_end = (cmd_closed_shape_end('end_closed_shape') + inst_end)
 
-   draw = (pyp.Optional(cmd_linear_int) +
-           pyp.Group(coord_xy + cmd_draw) +
-           inst_end)
+   draw = pyp.Group(pyp.Optional(cmd_linear_int) +
+           'X' + (integer)('x') +
+           'Y' + (integer)('y') +
+           pyp.Literal('D01').suppress() +
+           inst_end)('draw')
 
-   move = (pyp.Optional(cmd_linear_int) +
-           pyp.Group(coord_xy + cmd_move) +
-           inst_end)
+   move = pyp.Group(pyp.Optional(cmd_linear_int) +
+           'X' + (integer)('x') +
+           'Y' + (integer)('y') +
+           pyp.Literal('D02').suppress() +
+           inst_end)('move')
 
-   flash = (pyp.Optional(cmd_linear_int) +
-           pyp.Group(coord_xy + cmd_flash) +
-           inst_end)
+   flash = pyp.Group(pyp.Optional(cmd_linear_int) +
+           'X' + (integer)('x') +
+           'Y' + (integer)('y') +
+           pyp.Literal('D03').suppress() +
+           inst_end)('flash')
 
-   apperture_change = pyp.dictOf(apperture, floatnum) + inst_end
+   aperture_change = (pyp.Literal('D').suppress() + 
+                      pyp.Group(integer('number') + inst_end)('aperture_change'))
 
    # end of file (suppress)
-   the_end = (pyp.Literal('M02') + inst_end).suppress()
+   the_end = (pyp.Literal('M02') + inst_end)('end_of_gerber')
 
-   apperture_features = pyp.Group(apperture_change + pyp.OneOrMore(draw | move | flash))
 
-   grammar = (comment | units | gformat | app_def | polarity |
-              closed_shape_start | closed_shape_end |
-              apperture_features | 
-              draw | move | flash | apperture_change | the_end)
+   grammar = (comment | 
+              units | 
+              gformat | 
+              ap_def |
+              aperture_change |
+              draw | move | flash |
+              polarity |
+              closed_shape_start |
+              closed_shape_end |
+              the_end)
+
+   
 
    return pyp.OneOrMore(pyp.Group(grammar))
 
     Takes Gerber files as input and generates an SVG of them
     """
 
+    def parsed_grammar_to_dict(parsed_grammar):
+        """
+        Converts the Gerber parsing results to an SVG.
+        """ 
+ 
+        gerber_dict = {}
+        current_aperture = None
+
+        for line in parsed_grammar:
+            #line = line.dump()
+            print line.dump()
+            if line.dump(): 
+                if (line.format):
+                    if gerber_dict.get('format') is None:
+                        gerber_dict['format'] = {}
+                    tmp = gerber_dict['format']
+                    
+                    tmp['notation'] = line['format']['notation'] 
+                    tmp['zeros'] = line['format']['zeros']
+                    tmp['x'] = {}
+                    tmp['x']['integer'] = line['format']['x']['integer']
+                    tmp['x']['decimal'] = line['format']['x']['decimal']
+                    tmp['y'] = {}
+                    tmp['y']['integer'] = line['format']['x']['integer']
+                    tmp['y']['decimal'] = line['format']['x']['decimal']
+                 
+                elif (line.units):
+                    gerber_dict['units'] = line['units']['units']
+
+                elif (line.aperture_definition):
+                    tmp = {}
+                    if line['aperture_definition']['type'] == 'circle':
+                        tmp['type'] = 'circle'
+                        tmp['diameter'] = line['aperture_definition']['type']
+                        tmp['number'] = line['aperture_definition']['number']
+                    elif line['aperture_definition']['type'] == 'rect':
+                        tmp['type'] = 'rect'
+                        tmp['width'] = line['aperture_definition']['width']
+                        tmp['height'] = line['aperture_definition']['height']
+                        tmp['number'] = line['aperture_definition']['number']
+                    else:
+                        print "ERROR: cannot recognise aperture definition type"
+                    
+                    if gerber_dict.get('aperture-definitions') is None:
+                        gerber_dict['aperture-definitions'] = []
+                    
+                    gerber_dict['aperture-definitions'].append(tmp)
+
+                elif line.polarity_change:
+
+                    if gerber_dict.get('features') is None:
+                        gerber_dict['features'] = []
+  
+                    polarity = line['polarity_change']['polarity']
+                    polarity_dict = {}
+                    polarity_dict['polarity'] = polarity
+                    polarity_dict['shapes'] = []
+                    gerber_dict['features'].append(polarity_dict)
+
+                elif line.aperture_change:
+                    current_aperture = line.aperture_change['number']
+
+                elif line.start_closed_shape:
+                    tmp = {}
+                    tmp['type'] = 'fill'
+                    tmp['segments'] = []
+
+                    # TODO: consolidate logic
+                    if len(gerber_dict['features'][-1]['shapes']) > 0:
+                        if gerber_dict['features'][-1]['shapes'][-1]['type'] == None:
+                            gerber_dict['features'][-1]['shapes'][-1] = tmp
+                        else:
+                            gerber_dict['features'][-1]['shapes'].append(tmp)
+                    else:
+                        gerber_dict['features'][-1]['shapes'].append(tmp)
+                
+                elif line.move or line.draw or line.flash:
+
+                    # TODO: hack alert! (Got to get shit done, you know? Don't judge me!)
+                    if line.move:
+                        command_name = 'move'
+                        item = line.move
+                    if line.draw:
+                        command_name = 'draw'
+                        item = line.draw
+                    if line.flash:
+                        command_name = 'flash'
+                        item = line.flash
+
+                    # Check if the list is non empty and that the type is None.
+                    # If it is, this means that it's a new element created after
+                    # closing a closed shape element, so change None to 'stroke'.
+                    # Otherwise, it's the first element, so just append a new
+                    # 'stroke' element.
+                    if len(gerber_dict['features'][-1]['shapes']) > 0:
+                        if gerber_dict['features'][-1]['shapes'][-1]['type'] == None:
+                            gerber_dict['features'][-1]['shapes'][-1]['type'] = 'stroke'
+                    else:
+                        tmp = {}
+                        tmp['type'] = 'stroke'
+                        tmp['segments'] = []
+                        gerber_dict['features'][-1]['shapes'].append(tmp)
+                        
+                    point = Point(item['x'], item['y'])
+                    tmp = {}
+                    tmp['type'] = command_name
+                    tmp['coord'] = point
+                    tmp['aperture'] = current_aperture
+                    gerber_dict['features'][-1]['shapes'][-1]['segments'].append(tmp)
+
+                elif line.end_closed_shape:
+                    # This works by effectively "closing" the current list
+                    # element by creating a new element with a None "type".
+                    # This is changed by the next command that is processed.
+                    tmp = {}
+                    tmp['type'] = None
+                    tmp['segments'] = []
+                    gerber_dict['features'][-1]['shapes'].append(tmp)
+
+
+        print pprint(gerber_dict)
+
+
+        
+        return gerber_dict
+
+
     # directory for where to expect the Gerbers within the build path
     # regardless of the source of the Gerbers, the PCBmodE directory
     # structure is assumed
 
     parsed = gerber_grammar.parseString(gerber)
 
-    for item in parsed:
-        print item
+    gerber_dict = parsed_grammar_to_dict(parsed)
+
+    
+#    for item in parsed:
+#        print
+#        #print item.asDict()
+#        print item.dump()
 
 #    for line in gerber:
 #       print line