Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions tests/irdl/test_attr_declarative_assembly_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,19 @@ def test_empty_format_produces_empty_program():


@pytest.mark.parametrize(
"format_str, printed",
[("", ""), ("` `", " "), ("``", ""), ("`\\n`", "\n")],
"format_str, body, printed",
[
("", "", ""),
("` `", "", " "),
("``", "", ""),
("`\\n`", "", "\n"),
("`hello`", "hello", "hello"),
("`foo``bar`", "foo bar", "foo bar"),
],
)
def test_prints_and_parses_nothing(format_str: str, printed: str):
def test_print_and_parse(format_str: str, body: str, printed: str):
assert _print(format_str) == printed
assert _parse(format_str, "") == []
assert _parse(format_str, body) == []


def test_parse_attribute_end_to_end():
Expand All @@ -63,7 +70,7 @@ def test_parse_attribute_end_to_end():
[
("$foo", "unexpected token"),
("` `", "unexpected whitespace in directive"),
("`+`", "expected a whitespace directive"),
("`+`", "punctuation or identifier expected"),
],
)
def test_error(format_str: str, error: str):
Expand Down
36 changes: 30 additions & 6 deletions xdsl/irdl/declarative_assembly_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,14 @@ def _print_whitespace(printer: Printer, state: PrintingState, whitespace: str) -
state.should_emit_space = False


def _print_keyword(printer: Printer, state: PrintingState, keyword: str) -> None:
if state.should_emit_space:
printer.print_string(" ")
state.should_emit_space = True
state.last_was_punctuation = False
printer.print_string(keyword)


@dataclass(frozen=True)
class WhitespaceDirective(FormatDirective):
"""
Expand Down Expand Up @@ -1446,12 +1454,7 @@ def parse(self, parser: Parser, state: ParsingState) -> bool:
return parser.parse_optional_keyword(self.keyword) is not None

def print(self, printer: Printer, state: PrintingState, op: IRDLOperation) -> None:
if state.should_emit_space:
printer.print_string(" ")
state.should_emit_space = True
state.last_was_punctuation = False

printer.print_string(self.keyword)
_print_keyword(printer, state, self.keyword)

def is_optional_like(self) -> bool:
return True
Expand Down Expand Up @@ -1570,6 +1573,27 @@ def print(
_print_whitespace(printer, state, self.whitespace)


@dataclass(frozen=True)
class AttrKeywordDirective(AttrFormatDirective):
"""
A keyword directive for attribute/type assembly format.

Mirrors the op-side KeywordDirective: expects a specific identifier and
requests a space to be printed after.
"""

keyword: str
"""The identifier that should be printed."""

def parse(self, parser: AttrParser, state: AttrParsingState) -> bool:
return parser.parse_optional_keyword(self.keyword) is not None

def print(
self, printer: Printer, state: PrintingState, attr: ParametrizedAttribute, /
) -> None:
_print_keyword(printer, state, self.keyword)


@dataclass(frozen=True)
class AttrFormatProgram:
"""
Expand Down
9 changes: 8 additions & 1 deletion xdsl/irdl/declarative_assembly_format_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
AttrFormatDirective,
AttrFormatProgram,
AttributeVariable,
AttrKeywordDirective,
AttrWhitespaceDirective,
DenseArrayAttributeVariable,
Directive,
Expand Down Expand Up @@ -949,4 +950,10 @@ def parse_keyword_or_punctuation(self) -> AttrFormatDirective:
)
return AttrWhitespaceDirective(whitespace)

self.raise_error("expected a whitespace directive")
# Identifier case
ident = self.parse_optional_identifier()
if ident is None or ident == "`":
self.raise_error("punctuation or identifier expected")

self.parse_characters("`")
return AttrKeywordDirective(ident)
Loading