Skip to content

Commit

Permalink
Add SR class for wrapping whole SR blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Argmaster committed Aug 19, 2024
1 parent 3939c6f commit e8168fc
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 29 deletions.
2 changes: 2 additions & 0 deletions src/pygerber/gerberx3/ast/nodes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from pygerber.gerberx3.ast.nodes.aperture.AM import AM
from pygerber.gerberx3.ast.nodes.aperture.AM_close import AMclose
from pygerber.gerberx3.ast.nodes.aperture.AM_open import AMopen
from pygerber.gerberx3.ast.nodes.aperture.SR import SR
from pygerber.gerberx3.ast.nodes.aperture.SR_close import SRclose
from pygerber.gerberx3.ast.nodes.aperture.SR_open import SRopen
from pygerber.gerberx3.ast.nodes.attribute.TA import (
Expand Down Expand Up @@ -141,6 +142,7 @@
"ADR",
"AMclose",
"AMopen",
"SR",
"SRclose",
"SRopen",
"TA_AperFunction",
Expand Down
3 changes: 2 additions & 1 deletion src/pygerber/gerberx3/ast/nodes/aperture/AB_open.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING, Callable

from pygerber.gerberx3.ast.nodes.base import Node
from pygerber.gerberx3.ast.nodes.types import ApertureIdStr

if TYPE_CHECKING:
from typing_extensions import Self
Expand All @@ -15,7 +16,7 @@
class ABopen(Node):
"""Represents AB Gerber extended command."""

aperture_identifier: str
aperture_identifier: ApertureIdStr

def visit(self, visitor: AstVisitor) -> None:
"""Handle visitor call."""
Expand Down
3 changes: 2 additions & 1 deletion src/pygerber/gerberx3/ast/nodes/aperture/AD.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
from __future__ import annotations

from pygerber.gerberx3.ast.nodes.base import Node
from pygerber.gerberx3.ast.nodes.types import ApertureIdStr


class AD(Node):
"""Common base class for all commands adding new apertures."""

aperture_identifier: str
aperture_identifier: ApertureIdStr
32 changes: 32 additions & 0 deletions src/pygerber/gerberx3/ast/nodes/aperture/SR.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""`pygerber.nodes.aperture.SR` module contains definition of `SR` class."""

from __future__ import annotations

from typing import TYPE_CHECKING, Callable

from pygerber.gerberx3.ast.nodes.aperture.SR_close import SRclose
from pygerber.gerberx3.ast.nodes.aperture.SR_open import SRopen
from pygerber.gerberx3.ast.nodes.base import Node

if TYPE_CHECKING:
from typing_extensions import Self

from pygerber.gerberx3.ast.visitor import AstVisitor


class SR(Node):
"""Represents SR Gerber extended command."""

open: SRopen
nodes: list[Node]
close: SRclose

def visit(self, visitor: AstVisitor) -> None:
"""Handle visitor call."""
visitor.on_sr(self)

def get_visitor_callback_function(
self, visitor: AstVisitor
) -> Callable[[Self], None]:
"""Get callback function for the node."""
return visitor.on_sr
8 changes: 8 additions & 0 deletions src/pygerber/gerberx3/ast/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
MO,
OF,
SF,
SR,
TA,
TD,
TF,
Expand Down Expand Up @@ -182,6 +183,13 @@ def on_am_close(self, node: AMclose) -> None:
def on_am_open(self, node: AMopen) -> None:
"""Handle `AMopen` node."""

def on_sr(self, node: SR) -> None:
"""Handle `SR` root node."""
node.open.visit(self)
for inner_node in node.nodes:
inner_node.visit(self)
node.close.visit(self)

def on_sr_close(self, node: SRclose) -> None:
"""Handle `SRclose` node."""

Expand Down
69 changes: 48 additions & 21 deletions src/pygerber/gerberx3/parser/pyparsing/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
MO,
OF,
SF,
SR,
TD,
TF_MD5,
TO_C,
Expand Down Expand Up @@ -144,6 +145,9 @@ def __init__(
self.enable_debug = enable_debug
self.optimization = optimization

self.step_repeat_forward = pp.Forward()
self.aperture_block_forward = pp.Forward()

def build(self) -> pp.ParserElement:
"""Build the grammar."""

Expand All @@ -154,13 +158,13 @@ def _(s: str, loc: int, tokens: pp.ParseResults) -> File:
pp.OneOrMore(
pp.MatchFirst(
[
self.aperture(),
self.attribute,
self.d_codes_standalone,
self.g_codes,
self.load_commands,
self.m_codes,
self.aperture(),
self.attribute,
self.properties,
self.d_codes_standalone,
self.m_codes,
]
)
)
Expand Down Expand Up @@ -265,35 +269,35 @@ def aperture(self) -> pp.ParserElement:
"""Create a parser element capable of parsing apertures."""
return pp.MatchFirst(
[
self.aperture_block(),
self.aperture_block,
self.macro,
self.step_repeat,
self.add_aperture,
]
)

@pp.cached_property
def aperture_block(self) -> pp.ParserElement:
"""Create a parser element capable of parsing aperture blocks."""
aperture_block = pp.Forward()
self.aperture_block_forward = pp.Forward()

aperture_block <<= (
self.aperture_block_forward <<= (
(
self.ab_open.set_results_name("open")
+ pp.ZeroOrMore(
pp.MatchFirst(
[
self.attribute,
self.d_codes_standalone,
self.g_codes,
self.load_commands,
# Technically not valid according to standard.
self.m_codes,
self.properties,
self.d_codes_standalone,
# Other aperture altering commands.
self.macro,
self.step_repeat,
self.attribute,
self.add_aperture,
aperture_block,
self.step_repeat_forward,
self.aperture_block_forward,
self.macro,
# Technically not valid according to standard.
self.m_codes,
]
)
).set_results_name("nodes")
Expand All @@ -303,7 +307,7 @@ def aperture_block(self) -> pp.ParserElement:
.set_parse_action(self.make_unpack_callback(AB))
)

return aperture_block
return self.aperture_block_forward

@pp.cached_property
def ab_open(self) -> pp.ParserElement:
Expand Down Expand Up @@ -355,13 +359,36 @@ def am_close(self) -> pp.ParserElement:
@pp.cached_property
def step_repeat(self) -> pp.ParserElement:
"""Create a parser element capable of parsing step repeats."""
return pp.MatchFirst(
[
self.sr_close,
self.sr_open,
]
self.step_and_repeat_block_forward = pp.Forward()

self.step_and_repeat_block_forward <<= (
(
self.sr_open.set_results_name("open")
+ pp.ZeroOrMore(
pp.MatchFirst(
[
self.d_codes_standalone,
self.g_codes,
self.load_commands,
self.properties,
self.attribute,
self.add_aperture,
self.step_repeat_forward,
self.aperture_block_forward,
self.macro,
# Technically not valid according to standard.
self.m_codes,
]
)
).set_results_name("nodes")
+ self.sr_close.set_results_name("close")
)
.set_name("StepAndRepeatBlock")
.set_parse_action(self.make_unpack_callback(SR))
)

return self.step_and_repeat_block_forward

@pp.cached_property
def sr_open(self) -> pp.ParserElement:
"""Create a parser element capable of parsing SR-open."""
Expand Down
12 changes: 6 additions & 6 deletions test/gerberx3/test_ast/test_ast_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,41 +127,41 @@

NODE_SAMPLES: Dict[Type[Node], Node] = {
ABclose: ABclose(source="", location=0),
ABopen: ABopen(source="", location=0, aperture_identifier="D11"),
ABopen: ABopen(source="", location=0, aperture_identifier=ApertureIdStr("D11")),
ADC: ADC(
source="",
location=0,
aperture_identifier="D11",
aperture_identifier=ApertureIdStr("D11"),
diameter=0.1,
hole_diameter=0.05,
),
ADmacro: ADmacro(
source="",
location=0,
aperture_identifier="D11",
aperture_identifier=ApertureIdStr("D11"),
name="macro",
params=[1, 2],
),
ADO: ADO(
source="",
location=0,
aperture_identifier="D11",
aperture_identifier=ApertureIdStr("D11"),
width=0.1,
height=0.05,
hole_diameter=0.05,
),
ADR: ADR(
source="",
location=0,
aperture_identifier="D11",
aperture_identifier=ApertureIdStr("D11"),
width=0.1,
height=0.05,
hole_diameter=0.05,
),
ADP: ADP(
source="",
location=0,
aperture_identifier="D11",
aperture_identifier=ApertureIdStr("D11"),
outer_diameter=0.1,
vertices=4,
rotation=0.1,
Expand Down

0 comments on commit e8168fc

Please sign in to comment.