def _parse_line(self, line):
        # skip empty lines
        if not line.strip():
            return

        if line[0] == ';':
            comment_stmt = CommentStmt.from_excellon(line)
            self.statements.append(comment_stmt)

            # get format from altium comment
            if "FILE_FORMAT" in comment_stmt.comment:
                detected_format = tuple(
                    [int(x) for x in comment_stmt.comment.split('=')[1].split(":")])
                if detected_format:
                    self.format = detected_format

        elif line[:3] == 'M48':
            self.statements.append(HeaderBeginStmt())
            self.state = 'HEADER'

        elif line[0] == '%':
            self.statements.append(RewindStopStmt())
            if self.state == 'HEADER':
                self.state = 'DRILL'
            elif self.state == 'INIT':
                self.state = 'HEADER'

        elif line[:3] == 'M95':
            self.statements.append(HeaderEndStmt())
            if self.state == 'HEADER':
                self.state = 'DRILL'

        elif line[:3] == 'M15':
            self.statements.append(ZAxisRoutPositionStmt())

        elif line[:3] == 'M16':
            self.statements.append(RetractWithClampingStmt())

        elif line[:3] == 'M17':
            self.statements.append(RetractWithoutClampingStmt())

        elif line[:3] == 'M30':
            stmt = EndOfProgramStmt.from_excellon(line, self._settings())
            self.statements.append(stmt)

        elif line[:3] == 'G00':
            self.statements.append(RouteModeStmt())
            self.state = 'ROUT'

            stmt = CoordinateStmt.from_excellon(line[3:], self._settings())
            stmt.mode = self.state

            x = stmt.x
            y = stmt.y
            self.statements.append(stmt)
            if self.notation == 'absolute':
                if x is not None:
                    self.pos[0] = x
                if y is not None:
                    self.pos[1] = y
            else:
                if x is not None:
                    self.pos[0] += x
                if y is not None:
                    self.pos[1] += y

        elif line[:3] == 'G01':
            self.statements.append(RouteModeStmt())
            self.state = 'LINEAR'

            stmt = CoordinateStmt.from_excellon(line[3:], self._settings())
            stmt.mode = self.state

            x = stmt.x
            y = stmt.y
            self.statements.append(stmt)
            if self.notation == 'absolute':
                if x is not None:
                    self.pos[0] = x
                if y is not None:
                    self.pos[1] = y
            else:
                if x is not None:
                    self.pos[0] += x
                if y is not None:
                    self.pos[1] += y

        elif line[:3] == 'G05':
            self.statements.append(DrillModeStmt())
            self.state = 'DRILL'

        elif 'INCH' in line or 'METRIC' in line:
            stmt = UnitStmt.from_excellon(line)
            self.units = stmt.units
            self.zeros = stmt.zeros
            self.statements.append(stmt)

        elif line[:3] == 'M71' or line[:3] == 'M72':
            stmt = MeasuringModeStmt.from_excellon(line)
            self.units = stmt.units
            self.statements.append(stmt)

        elif line[:3] == 'ICI':
            stmt = IncrementalModeStmt.from_excellon(line)
            self.notation = 'incremental' if stmt.mode == 'on' else 'absolute'
            self.statements.append(stmt)

        elif line[:3] == 'VER':
            stmt = VersionStmt.from_excellon(line)
            self.statements.append(stmt)

        elif line[:4] == 'FMAT':
            stmt = FormatStmt.from_excellon(line)
            self.statements.append(stmt)

        elif line[:3] == 'G40':
            self.statements.append(CutterCompensationOffStmt())

        elif line[:3] == 'G41':
            self.statements.append(CutterCompensationLeftStmt())

        elif line[:3] == 'G42':
            self.statements.append(CutterCompensationRightStmt())

        elif line[:3] == 'G90':
            self.statements.append(AbsoluteModeStmt())
            self.notation = 'absolute'

        elif line[0] == 'F':
            infeed_rate_stmt = ZAxisInfeedRateStmt.from_excellon(line)
            self.statements.append(infeed_rate_stmt)

        elif line[0] == 'T' and self.state == 'HEADER':
            tool = ExcellonTool.from_excellon(line, self._settings())
            self.tools[tool.number] = tool
            self.statements.append(tool)

        elif line[0] == 'T' and self.state != 'HEADER':
            stmt = ToolSelectionStmt.from_excellon(line)
            self.statements.append(stmt)

            # T0 is used as END marker, just ignore
            if stmt.tool != 0:
                # FIXME: for weird files with no tools defined, original calc
                # from gerbv
                if stmt.tool not in self.tools:
                    if self._settings().units == "inch":
                        diameter = (16 + 8 * stmt.tool) / 1000.0
                    else:
                        diameter = metric((16 + 8 * stmt.tool) / 1000.0)

                    tool = ExcellonTool(
                        self._settings(), number=stmt.tool, diameter=diameter)
                    self.tools[tool.number] = tool

                    # FIXME: need to add this tool definition inside header to
                    # make sure it is properly written
                    for i, s in enumerate(self.statements):
                        if isinstance(s, ToolSelectionStmt) or isinstance(s, ExcellonTool):
                            self.statements.insert(i, tool)
                            break

                self.active_tool = self.tools[stmt.tool]

        elif line[0] == 'R' and self.state != 'HEADER':
            stmt = RepeatHoleStmt.from_excellon(line, self._settings())
            self.statements.append(stmt)
            for i in range(stmt.count):
                self.pos[0] += stmt.xdelta if stmt.xdelta is not None else 0
                self.pos[1] += stmt.ydelta if stmt.ydelta is not None else 0
                self.hits.append(DrillHit(self.active_tool, tuple(self.pos)))
                self.active_tool._hit()

        elif line[0] in ['X', 'Y']:
            stmt = CoordinateStmt.from_excellon(line, self._settings())
            x = stmt.x
            y = stmt.y
            self.statements.append(stmt)
            if self.notation == 'absolute':
                if x is not None:
                    self.pos[0] = x
                if y is not None:
                    self.pos[1] = y
            else:
                if x is not None:
                    self.pos[0] += x
                if y is not None:
                    self.pos[1] += y
            if self.state == 'DRILL':
                self.hits.append(DrillHit(self.active_tool, tuple(self.pos)))
                self.active_tool._hit()
        else:
            self.statements.append(UnknownStmt.from_excellon(line))
dataset/ETHPy150Open curtacircuitos/pcb-tools/gerber/excellon.py/ExcellonParser._parse_line/original