<commit_before># gerber parser class
# keeps track of coordinate format
# takes a gerber block object and acts accordingly

# parse coordinate function
parseCoord = require './coord-parser'

# constants
# regular expression to match a coordinate
reCOORD = /([XYIJ][+-]?\d+){1,4}/g

class GerberParser
  constructor: ->
    # coordinate format (places and zero suppression)
    @format = { zero: null, places: null }

  # parse a format block
  parseFormat: (p, c) ->
    zero = if p[2] is 'L' or p[2] is 'T' then p[2] else null
    nota = if p[3] is 'A' or p[3] is 'I' then p[3] else null
    if p[4] is 'X' and p[7] is 'Y' and p[5..6] is p[8..9] and
    p[5] < 8 and p[6] < 8
      places = [ +p[5], +p[6] ]
    if not places? or not nota? or not zero?
      throw new Error "invalid format specification"
    @format.zero = zero; @format.places = places
    unless c.set? then c.set = {}
    c.set.notation = nota

  # parse a aperture definition block
  parseToolDef: (p, c) ->
    unless c.tool? then c.tool = {}
    code = p.match(/^ADD\d{2,}/)?[0][2..]
    # get the shape and modifiers
    [shape, mods] = p[2+code.length..].split ','
    mods = mods?.split 'X'
    # remove leading zeros from tool code
    code = code[0] + code[2..] while code[1] is '0'
    switch shape
      # circle
      when 'C'
        if mods.length > 2 then hole = { width: +mods[1], height: +mods[2] }
        else if mods.length > 1 then hole = { dia: +mods[1] }
        c.tool[code] = { dia: +mods[0] }
        if hole? then c.tool[code].hole = hole
      # rectangle, obround
      when 'R', 'O'
        if mods.length > 3 then hole = { width: +mods[2], height: +mods[3] }
        else if mods.length > 2 then hole = { dia: +mods[2] }
        c.tool[code] = {width: +mods[0], height: +mods[1] }
        if shape is 'O' then c.tool[code].obround = true
        if hole? then c.tool[code].hole = hole
      # polygon
      when 'P'
        if mods.length > 4 then hole = { width: +mods[3], height: +mods[4] }
        else if mods.length > 3 then hole = { dia: +mods[3] }
        c.tool[code] = { dia: +mods[0], verticies: +mods[1] }
        if mods.length > 2 then c.tool[code].degrees = +mods[2]
        if hole? then c.tool[code].hole = hole
      # else aperture macro
      else
        mods = (+m for m in (mods ? []))
        c.tool[code] = { macro: shape, mods: mods }

  # parse a block for the command
  parseCommand: (block = {}) ->
    # command
    c = {}
    # we're either going to have a parameter or a block
    if param = block.param
      # param will be an array of blocks, so let's loop through them
      for p in param
        # parameter code is first two letters
        switch code = p[0..1]
          # format set
          when 'FS'
            @parseFormat p, c
          # unit set
          when 'MO'
            u = p[2..3]
            unless c.set? then c.set = {}
            if u is 'IN' then c.set.units = 'in'
            else if u is 'MM' then c.set.units = 'mm'
            else throw new Error "#{p} is an invalid units setting"<commit_msg>all unit tests passing<commit_after># gerber parser class
# keeps track of coordinate format
# takes a gerber block object and acts accordingly

# parse coordinate function
parseCoord = require './coord-parser'
# get integer function
getInteger = require './get-integer'

# constants
# regular expression to match a coordinate
reCOORD = /([XYIJ][+-]?\d+){1,4}/g

class GerberParser
  constructor: ->
    # coordinate format (places and zero suppression)
    @format = { zero: null, places: null }

  # parse a format block
  parseFormat: (p, c) ->
    zero = if p[2] is 'L' or p[2] is 'T' then p[2] else null
    nota = if p[3] is 'A' or p[3] is 'I' then p[3] else null
    if p[4] is 'X' and p[7] is 'Y' and p[5..6] is p[8..9] and
    p[5] < 8 and p[6] < 8
      places = [ +p[5], +p[6] ]
    if not places? or not nota? or not zero?
      throw new Error "invalid format specification"
    @format.zero = zero; @format.places = places
    unless c.set? then c.set = {}
    c.set.notation = nota

  # parse a aperture definition block
  parseToolDef: (p, c) ->
    unless c.tool? then c.tool = {}
    code = p.match(/^ADD\d{2,}/)?[0][2..]
    # get the shape and modifiers
    [shape, mods] = p[2+code.length..].split ','
    mods = mods?.split 'X'
    # remove leading zeros from tool code
    code = code[0] + code[2..] while code[1] is '0'
    switch shape
      # circle
      when 'C'
        if mods.length > 2 then hole = {
          width:  getInteger mods[1], { places: @format.places }
          height: getInteger mods[2], { places: @format.places }
        }
        else if mods.length > 1 then hole = {
          dia: getInteger mods[1], { places: @format.places }
        }
        c.tool[code] = {
          dia: getInteger mods[0], { places: @format.places }
        }
        if hole? then c.tool[code].hole = hole
      # rectangle, obround
      when 'R', 'O'
        if mods.length > 3 then hole = {
          width:  getInteger mods[2], { places: @format.places }
          height: getInteger mods[3], { places: @format.places }
        }
        else if mods.length > 2 then hole = {
          dia: getInteger mods[2], { places: @format.places }
        }
        c.tool[code] = {
          width:  getInteger mods[0], { places: @format.places }
          height: getInteger mods[1], { places: @format.places }
        }
        if shape is 'O' then c.tool[code].obround = true
        if hole? then c.tool[code].hole = hole
      # polygon
      when 'P'
        if mods.length > 4 then hole = {
          width:  getInteger mods[3], { places: @format.places }
          height: getInteger mods[4], { places: @format.places }
        }
        else if mods.length > 3 then hole = {
          dia: getInteger mods[3], { places: @format.places }
        }
        c.tool[code] = {
          dia:       getInteger mods[0], { places: @format.places }
          verticies: +mods[1]
        }
        if mods.length > 2 then c.tool[code].degrees = +mods[2]
        if hole? then c.tool[code].hole = hole
      # else aperture macro
      else
        mods = (+m for m in (mods ? []))
        c.tool[code] = { macro: shape, mods: mods }

  # parse a block for the command
  parseCommand: (block = {}) ->
    # command
    c = {}
    # we're either going to have a parameter or a block
    if param = block.param
      # param will be an array of blocks, so let's loop through them
      for p in param
        # parameter code is first two letters
        switch code = p[0..1]
          # format set
          when 'FS'
            @parseFormat p, c
          # unit set
          when 'MO'
            u = p[2..3]
            unless c.set? then c.set = {}
            if u is 'IN' then c.set.units = 'in'
            else if u is 'MM' then c.set.units = 'mm'
            else throw new Error "#{p} is an invalid units setting"
{'fraction_non_alphanumeric': 0.13442338301258863, 'fraction_numerical': 0.015627260888438722, 'mean_word_length': 2.0342405618964006, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3361804', 'n_tokens_mistral': 2368, 'n_tokens_neox': 2308, 'n_words': 793}