From ac2a7d9282580c08f97935b8ccad5078a3a30f3f Mon Sep 17 00:00:00 2001 From: James Westman Date: Tue, 11 Apr 2023 21:26:37 -0500 Subject: [PATCH] Add StringValue Makes the grammar more specific in a few places that take only a string literal or translated string. --- blueprintcompiler/language/__init__.py | 1 + .../language/adw_message_dialog.py | 6 +-- .../language/gtk_combo_box_text.py | 12 ++---- blueprintcompiler/language/gtk_menu.py | 14 +++---- blueprintcompiler/language/gtk_string_list.py | 11 +++-- blueprintcompiler/language/values.py | 21 ++++++++++ blueprintcompiler/outputs/xml/__init__.py | 41 +++++++++++-------- tests/sample_errors/obj_in_string_list.err | 2 +- 8 files changed, 66 insertions(+), 42 deletions(-) diff --git a/blueprintcompiler/language/__init__.py b/blueprintcompiler/language/__init__.py index d251fae..45e5361 100644 --- a/blueprintcompiler/language/__init__.py +++ b/blueprintcompiler/language/__init__.py @@ -37,6 +37,7 @@ from .values import ( NumberLiteral, ObjectValue, QuotedLiteral, + StringValue, Translated, TranslatedWithContext, TranslatedWithoutContext, diff --git a/blueprintcompiler/language/adw_message_dialog.py b/blueprintcompiler/language/adw_message_dialog.py index 2911735..3aa1911 100644 --- a/blueprintcompiler/language/adw_message_dialog.py +++ b/blueprintcompiler/language/adw_message_dialog.py @@ -22,14 +22,14 @@ from ..decompiler import truthy, decompile_translatable from .common import * from .contexts import ValueTypeCtx from .gobject_object import ObjectContent, validate_parent_type -from .values import QuotedLiteral, Translated +from .values import StringValue class Response(AstNode): grammar = [ UseIdent("id"), Match(":").expected(), - AnyOf(QuotedLiteral, Translated).expected("a value"), + to_parse_node(StringValue).expected("a string or translatable string"), ZeroOrMore( AnyOf(Keyword("destructive"), Keyword("suggested"), Keyword("disabled")) ), @@ -52,7 +52,7 @@ class Response(AstNode): return "disabled" not in self.tokens @property - def value(self) -> T.Union[QuotedLiteral, Translated]: + def value(self) -> StringValue: return self.children[0] @context(ValueTypeCtx) diff --git a/blueprintcompiler/language/gtk_combo_box_text.py b/blueprintcompiler/language/gtk_combo_box_text.py index e1a8a12..b20eaf0 100644 --- a/blueprintcompiler/language/gtk_combo_box_text.py +++ b/blueprintcompiler/language/gtk_combo_box_text.py @@ -22,7 +22,7 @@ from .attributes import BaseTypedAttribute from .gobject_object import ObjectContent, validate_parent_type from .common import * from .contexts import ValueTypeCtx -from .values import Value +from .values import StringValue class Item(AstNode): @@ -31,12 +31,8 @@ class Item(AstNode): return self.tokens["name"] @property - def value(self) -> Value: - return self.children[Value][0] - - @context(ValueTypeCtx) - def value_type(self) -> ValueTypeCtx: - return ValueTypeCtx(StringType()) + def value(self) -> StringValue: + return self.children[StringValue][0] item = Group( @@ -48,7 +44,7 @@ item = Group( ":", ] ), - Value, + StringValue, ], ) diff --git a/blueprintcompiler/language/gtk_menu.py b/blueprintcompiler/language/gtk_menu.py index df4b031..2d3b65b 100644 --- a/blueprintcompiler/language/gtk_menu.py +++ b/blueprintcompiler/language/gtk_menu.py @@ -19,7 +19,7 @@ import typing as T -from blueprintcompiler.language.values import Value +from blueprintcompiler.language.values import StringValue from .attributes import BaseAttribute from .gobject_object import Object, ObjectContent @@ -58,8 +58,8 @@ class MenuAttribute(AstNode): return self.tokens["name"] @property - def value(self) -> Value: - return self.children[Value][0] + def value(self) -> StringValue: + return self.children[StringValue][0] @context(ValueTypeCtx) def value_type(self) -> ValueTypeCtx: @@ -85,7 +85,7 @@ menu_attribute = Group( [ UseIdent("name"), ":", - Err(Value, "Expected a value"), + Err(StringValue, "Expected string or translated string"), Match(";").expected(), ], ) @@ -109,7 +109,7 @@ menu_item_shorthand = Group( "(", Group( MenuAttribute, - [UseLiteral("name", "label"), Value], + [UseLiteral("name", "label"), StringValue], ), Optional( [ @@ -118,14 +118,14 @@ menu_item_shorthand = Group( [ Group( MenuAttribute, - [UseLiteral("name", "action"), Value], + [UseLiteral("name", "action"), StringValue], ), Optional( [ ",", Group( MenuAttribute, - [UseLiteral("name", "icon"), Value], + [UseLiteral("name", "icon"), StringValue], ), ] ), diff --git a/blueprintcompiler/language/gtk_string_list.py b/blueprintcompiler/language/gtk_string_list.py index b07fa69..c6aed81 100644 --- a/blueprintcompiler/language/gtk_string_list.py +++ b/blueprintcompiler/language/gtk_string_list.py @@ -20,17 +20,16 @@ from .attributes import BaseTypedAttribute from .gobject_object import ObjectContent, validate_parent_type -from .values import Value, Translated +from .values import StringValue from .common import * -from .contexts import ValueTypeCtx class Item(AstNode): - grammar = Value + grammar = StringValue - @context(ValueTypeCtx) - def value_type(self) -> ValueTypeCtx: - return ValueTypeCtx(StringType()) + @property + def child(self) -> StringValue: + return self.children[StringValue][0] class Strings(AstNode): diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 0141a2f..bfc17c6 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -368,3 +368,24 @@ class Value(AstNode): self, ) -> T.Union[PropertyBinding, Binding, Translated, ObjectValue, Flags, Literal]: return self.children[0] + + +class StringValue(AstNode): + grammar = AnyOf(Translated, QuotedLiteral) + + @property + def child( + self, + ) -> T.Union[Translated, QuotedLiteral]: + return self.children[0] + + @property + def string(self) -> str: + if isinstance(self.child, Translated): + return self.child.child.string + else: + return self.child.value + + @context(ValueTypeCtx) + def value_type(self) -> ValueTypeCtx: + return ValueTypeCtx(StringType()) diff --git a/blueprintcompiler/outputs/xml/__init__.py b/blueprintcompiler/outputs/xml/__init__.py index 8a2bd6c..0daae44 100644 --- a/blueprintcompiler/outputs/xml/__init__.py +++ b/blueprintcompiler/outputs/xml/__init__.py @@ -78,7 +78,13 @@ class XmlOutput(OutputFormat): if isinstance(child, Menu): self._emit_menu(child, xml) elif isinstance(child, MenuAttribute): - self._emit_attribute("attribute", "name", child.name, child.value, xml) + xml.start_tag( + "attribute", + name=child.name, + **self._translated_string_attrs(child.value.child), + ) + xml.put_text(child.value.string) + xml.end_tag() else: raise CompilerBugError() xml.end_tag() @@ -235,7 +241,12 @@ class XmlOutput(OutputFormat): xml.end_tag() def _emit_attribute( - self, tag: str, attr: str, name: str, value: Value, xml: XmlEmitter + self, + tag: str, + attr: str, + name: str, + value: T.Union[Value, StringValue], + xml: XmlEmitter, ): attrs = {attr: name} @@ -243,6 +254,10 @@ class XmlOutput(OutputFormat): xml.start_tag(tag, **attrs, **self._translated_string_attrs(value.child)) xml.put_text(value.child.child.string) xml.end_tag() + elif isinstance(value.child, QuotedLiteral): + xml.start_tag(tag, **attrs) + xml.put_text(value.child.value) + xml.end_tag() else: xml.start_tag(tag, **attrs) self._emit_value(value, xml) @@ -282,29 +297,21 @@ class XmlOutput(OutputFormat): xml.start_tag( "response", id=response.id, - **self._translated_string_attrs(response.value), + **self._translated_string_attrs(response.value.child), enabled=None if response.enabled else "false", appearance=response.appearance, ) - if isinstance(response.value, Translated): - xml.put_text(response.value.child.string) - else: - xml.put_text(response.value.value) + xml.put_text(response.value.string) xml.end_tag() xml.end_tag() elif isinstance(extension, Strings): xml.start_tag("items") - for prop in extension.children: - value = prop.children[Value][0] - if isinstance(value.child, Translated): - xml.start_tag("item", **self._translated_string_attrs(value)) - xml.put_text(value.child.child.string) - xml.end_tag() - else: - xml.start_tag("item") - self._emit_value(value, xml) - xml.end_tag() + for string in extension.children: + value = string.child + xml.start_tag("item", **self._translated_string_attrs(value.child)) + xml.put_text(value.string) + xml.end_tag() xml.end_tag() elif isinstance(extension, ListItemFactory): child_xml = XmlEmitter() diff --git a/tests/sample_errors/obj_in_string_list.err b/tests/sample_errors/obj_in_string_list.err index 67628a3..9988af9 100644 --- a/tests/sample_errors/obj_in_string_list.err +++ b/tests/sample_errors/obj_in_string_list.err @@ -1 +1 @@ -5,5,2,Cannot assign Gtk.Button to string +4,3,22,Unexpected tokens