From be667a2b9c8412a74d6909f37390e48b0ca14e49 Mon Sep 17 00:00:00 2001 From: jgcodes2020 Date: Tue, 24 Dec 2024 08:50:37 -0500 Subject: [PATCH] implement variant parsing --- blueprintcompiler/language/gtk_menu.py | 5 +- blueprintcompiler/language/values.py | 5 +- blueprintcompiler/language/variant.py | 119 +++++++++++++++++++++++++ variant-test.blp | 26 +++--- 4 files changed, 139 insertions(+), 16 deletions(-) create mode 100644 blueprintcompiler/language/variant.py diff --git a/blueprintcompiler/language/gtk_menu.py b/blueprintcompiler/language/gtk_menu.py index 9e76d61..a703a76 100644 --- a/blueprintcompiler/language/gtk_menu.py +++ b/blueprintcompiler/language/gtk_menu.py @@ -137,7 +137,10 @@ menu_attribute = Group( [ UseIdent("name"), ":", - Err(AnyOf(StringValue, VariantValue), "Expected string or translated string"), + Err( + AnyOf(StringValue, VariantValue), + "Expected string, translated string, or variant", + ), Match(";").expected(), ], ) diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 975dd95..4c7aab9 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -26,6 +26,7 @@ from .common import * from .contexts import ScopeCtx, ValueTypeCtx from .gobject_object import Object from .types import TypeName +from .variant import VarContent class Translated(AstNode): @@ -373,7 +374,7 @@ class IdentLiteral(AstNode): class VariantValue(AstNode): - grammar = ["variant", "<", UseQuoted("type"), ">", "(", UseQuoted("value"), ")"] + grammar = ["variant", "<", UseQuoted("type"), ">", "(", VarContent, ")"] @property def var_type(self) -> str: @@ -381,7 +382,7 @@ class VariantValue(AstNode): @property def var_value(self) -> str: - return self.tokens["value"] + return self.children[0].content @validate() def validate_for_type(self) -> None: diff --git a/blueprintcompiler/language/variant.py b/blueprintcompiler/language/variant.py new file mode 100644 index 0000000..62c8458 --- /dev/null +++ b/blueprintcompiler/language/variant.py @@ -0,0 +1,119 @@ +import typing as T + +from blueprintcompiler.gir import ArrayType +from blueprintcompiler.lsp_utils import SemanticToken + +from .common import * +from .contexts import ScopeCtx, ValueTypeCtx +from .gobject_object import Object +from .types import TypeName + +VAR_CONTENT_HOOKS = [] + + +class VarContent(AstNode): + grammar = AnyOf(*VAR_CONTENT_HOOKS) + + @property + def content(self) -> str: + return self.children[0].content + + +class VarContentBool(AstNode): + grammar = AnyOf( + [Keyword("true"), UseLiteral("value", True)], + [Keyword("false"), UseLiteral("value", False)], + ) + + @property + def content(self) -> str: + if self.tokens["value"]: + return "true" + else: + return "false" + + +class VarContentString(AstNode): + grammar = UseQuoted("value") + + @property + def content(self) -> str: + return self.tokens["value"] + + +class VarContentNumber(AstNode): + grammar = UseNumberText("value") + + @property + def content(self) -> str: + return self.tokens["value"] + + +class VarContentTuple(AstNode): + grammar = ["(", Delimited(VarContent, ","), ")"] + + @property + def content(self) -> str: + inner = ", ".join(child.content for child in self.children) + return f"({inner})" + + +class VarContentArray(AstNode): + grammar = ["[", Delimited(VarContent, ","), "]"] + + @property + def content(self) -> str: + inner = ", ".join(child.content for child in self.children) + return f"[{inner}]" + + +class VarContentDictEntry(AstNode): + grammar = ["{", VarContent, ",", VarContent, "}"] + + @property + def content(self): + return f"{{{self.children[0].content}, {self.children[1].content}}}" + + +class VarContentDict(AstNode): + grammar = ["{", Delimited([VarContent, ":", VarContent], ","), "}"] + + @property + def content(self) -> str: + inner = ", ".join(child.content for child in self.children) + return f"{{{inner}}}" + + +class VarContentVariant(AstNode): + grammar = ["<", VarContent, ">"] + + @property + def content(self) -> str: + return f"<{self.children[0].content}>" + + +class VarContentMaybe(AstNode): + grammar = AnyOf( + [Keyword("just"), VarContent], + [Keyword("nothing")], + ) + + @property + def content(self) -> str: + if self.children[0] is not None: + return f"just {self.children[0].content}" + else: + return "nothing" + + +VarContent.grammar.children = [ + VarContentString, + VarContentNumber, + VarContentBool, + VarContentMaybe, + VarContentTuple, + VarContentDict, + VarContentDictEntry, + VarContentArray, + VarContentVariant, +] diff --git a/variant-test.blp b/variant-test.blp index f69522f..8cdca87 100644 --- a/variant-test.blp +++ b/variant-test.blp @@ -1,16 +1,16 @@ using Gtk 4.0; -menu root { - submenu { - name: "one"; - item { - action: "app.foo_bar"; - target: variant<"s">("\"one\""); - } - } -} - -Button { - action-name: "app.shave_yak"; - action-target: variant<"y">("8"); +$BlueprintTestObject { + // test-one: variant<"s">("one"); + test-zero: variant<"b">(true); + test-one: variant<"s">("one"); + test-two: variant<"i">(2); + test-three: variant<"(ii)">((3, 4)); + test-four: variant<"ai">([5, 6]); + test-five: variant<"{sv}">({"key", <"value">}); + test-six: variant<"a{ss}">({ + "GLib": "2.24", + "Gtk": "4.16" + }); + test-seven: variant<"ams">([just "2", nothing]); } \ No newline at end of file