hassl 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hassl/cli.py +3 -3
- hassl/parser/hassl.lark +139 -0
- hassl/parser/loader.py +6 -0
- {hassl-0.2.0.dist-info → hassl-0.2.1.dist-info}/METADATA +1 -1
- {hassl-0.2.0.dist-info → hassl-0.2.1.dist-info}/RECORD +9 -7
- {hassl-0.2.0.dist-info → hassl-0.2.1.dist-info}/WHEEL +0 -0
- {hassl-0.2.0.dist-info → hassl-0.2.1.dist-info}/entry_points.txt +0 -0
- {hassl-0.2.0.dist-info → hassl-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {hassl-0.2.0.dist-info → hassl-0.2.1.dist-info}/top_level.txt +0 -0
hassl/cli.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import os, json
|
|
3
|
+
from .parser.loader import load_grammar_text
|
|
3
4
|
from .parser.transform import HasslTransformer
|
|
4
5
|
from .ast.nodes import Program
|
|
5
6
|
from lark import Lark
|
|
@@ -7,11 +8,10 @@ from .semantics.analyzer import analyze
|
|
|
7
8
|
from .codegen.package import emit_package
|
|
8
9
|
from .codegen import generate as codegen_generate
|
|
9
10
|
|
|
10
|
-
GRAMMAR_PATH = os.path.join(os.path.dirname(__file__), "parser", "hassl.lark")
|
|
11
|
+
#GRAMMAR_PATH = os.path.join(os.path.dirname(__file__), "parser", "hassl.lark")
|
|
11
12
|
|
|
12
13
|
def parse_hassl(text: str) -> Program:
|
|
13
|
-
|
|
14
|
-
grammar = f.read()
|
|
14
|
+
grammar = load_grammar_text()
|
|
15
15
|
parser = Lark(grammar, start="start", parser="lalr", maybe_placeholders=False)
|
|
16
16
|
tree = parser.parse(text)
|
|
17
17
|
program = HasslTransformer().transform(tree)
|
hassl/parser/hassl.lark
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// HASSL grammar — unified if_clause w/ optional inside/outside qualifier
|
|
2
|
+
// + additive schedule support
|
|
3
|
+
|
|
4
|
+
start: stmt*
|
|
5
|
+
|
|
6
|
+
stmt: alias
|
|
7
|
+
| sync
|
|
8
|
+
| rule
|
|
9
|
+
| schedule_decl // NEW (additive)
|
|
10
|
+
|
|
11
|
+
// --- Aliases ---
|
|
12
|
+
alias: "alias" CNAME "=" entity
|
|
13
|
+
|
|
14
|
+
// --- Sync ---
|
|
15
|
+
sync: "sync" synctype "[" entity_list "]" "as" CNAME syncopts?
|
|
16
|
+
|
|
17
|
+
ONOFF: "onoff"
|
|
18
|
+
DIMMER: "dimmer"
|
|
19
|
+
ATTRIBUTE: "attribute"
|
|
20
|
+
SHARED: "shared"
|
|
21
|
+
ALL: "all"
|
|
22
|
+
synctype: ONOFF | DIMMER | ATTRIBUTE | SHARED | ALL
|
|
23
|
+
|
|
24
|
+
syncopts: "{" ("invert" ":" entity_list) "}"
|
|
25
|
+
|
|
26
|
+
// --- Rules ---
|
|
27
|
+
// Allow qualifier inside (...) and/or after ) — both optional
|
|
28
|
+
// (augmented to allow schedule clauses inside rules)
|
|
29
|
+
rule: "rule" CNAME ":" rule_clause+
|
|
30
|
+
|
|
31
|
+
rule_clause: if_clause
|
|
32
|
+
| rule_schedule_use // NEW
|
|
33
|
+
| rule_schedule_inline // NEW
|
|
34
|
+
|
|
35
|
+
if_clause: "if" "(" expr qualifier? ")" qualifier? "then" actions
|
|
36
|
+
|
|
37
|
+
// ---- Conditions ----
|
|
38
|
+
qualifier: "not_by" ( "this" | "any_hassl" | "rule" "(" CNAME ")" )
|
|
39
|
+
|
|
40
|
+
?expr: expr "||" andexpr -> or_
|
|
41
|
+
| andexpr
|
|
42
|
+
?andexpr: andexpr "&&" term -> and_
|
|
43
|
+
| term
|
|
44
|
+
?term: "!" term -> not_
|
|
45
|
+
| "(" expr ")"
|
|
46
|
+
| comparison
|
|
47
|
+
|
|
48
|
+
comparison: operand OP operand
|
|
49
|
+
| operand -> bare_operand
|
|
50
|
+
|
|
51
|
+
OP: "==" | "!=" | "<" | ">" | "<=" | ">="
|
|
52
|
+
|
|
53
|
+
operand: entity | CNAME | STATE | NUMBER | STRING
|
|
54
|
+
|
|
55
|
+
STATE: "on" | "off"
|
|
56
|
+
NUMBER: INT | SIGNED_NUMBER
|
|
57
|
+
|
|
58
|
+
// ---- Actions ----
|
|
59
|
+
actions: action (";" action)*
|
|
60
|
+
|
|
61
|
+
action: assign
|
|
62
|
+
| attr_assign
|
|
63
|
+
| waitact
|
|
64
|
+
| rulectrl
|
|
65
|
+
| tagact
|
|
66
|
+
|
|
67
|
+
assign: CNAME "=" STATE ("for" dur)?
|
|
68
|
+
|
|
69
|
+
// Attribute assignment: allow alias.attr and full entity paths
|
|
70
|
+
attr_assign: CNAME "." CNAME ("." CNAME)* "." CNAME "=" NUMBER
|
|
71
|
+
| CNAME "." CNAME "=" NUMBER
|
|
72
|
+
|
|
73
|
+
waitact: "wait" "(" condition "for" dur ")" action
|
|
74
|
+
// condition used by wait(): allow expr + optional qualifier inside the parens
|
|
75
|
+
condition: expr qualifier?
|
|
76
|
+
|
|
77
|
+
rulectrl: ("disable" | "enable") "rule" CNAME ("for" dur | "until" timepoint)
|
|
78
|
+
tagact: "tag" CNAME "=" (STRING | CNAME | NUMBER)
|
|
79
|
+
|
|
80
|
+
// Durations
|
|
81
|
+
dur: INT UNIT
|
|
82
|
+
UNIT: "ms" | "s" | "m" | "h" | "d"
|
|
83
|
+
|
|
84
|
+
// Timepoint placeholder (kept simple)
|
|
85
|
+
timepoint: CNAME
|
|
86
|
+
|
|
87
|
+
// ---------- Schedules (additive) ----------
|
|
88
|
+
SCHEDULE: "schedule"
|
|
89
|
+
USE: "use"
|
|
90
|
+
FROM: "from"
|
|
91
|
+
TO: "to"
|
|
92
|
+
UNTIL: "until"
|
|
93
|
+
ENABLE: "enable"
|
|
94
|
+
DISABLE: "disable"
|
|
95
|
+
SUNRISE: "sunrise"
|
|
96
|
+
SUNSET: "sunset"
|
|
97
|
+
|
|
98
|
+
TIME_HHMM: /[0-2]?\d:[0-5]\d/
|
|
99
|
+
OFFSET: /[+-]\d+(ms|s|m|h|d)/
|
|
100
|
+
|
|
101
|
+
// Reusable named schedule declarations
|
|
102
|
+
schedule_decl: SCHEDULE CNAME ":" schedule_clause+
|
|
103
|
+
|
|
104
|
+
// Clauses usable both in declarations and inline
|
|
105
|
+
schedule_clause: schedule_op FROM time_spec schedule_end? ";"
|
|
106
|
+
schedule_op: ENABLE | DISABLE
|
|
107
|
+
schedule_end: TO time_spec -> schedule_to
|
|
108
|
+
| UNTIL time_spec -> schedule_until
|
|
109
|
+
|
|
110
|
+
// Rule-level usage
|
|
111
|
+
rule_schedule_use: SCHEDULE USE name_list ";"
|
|
112
|
+
name_list: CNAME ("," CNAME)*
|
|
113
|
+
|
|
114
|
+
// Inline schedule block inside a rule
|
|
115
|
+
rule_schedule_inline: SCHEDULE schedule_clause+
|
|
116
|
+
|
|
117
|
+
// Time specifications
|
|
118
|
+
time_spec: TIME_HHMM -> time_clock
|
|
119
|
+
| sun_spec
|
|
120
|
+
| entity
|
|
121
|
+
| CNAME
|
|
122
|
+
|
|
123
|
+
sun_spec: (SUNRISE|SUNSET) OFFSET? -> time_sun
|
|
124
|
+
|
|
125
|
+
// ---- Atoms ----
|
|
126
|
+
entity_list: member ("," member)*
|
|
127
|
+
member: entity | CNAME
|
|
128
|
+
|
|
129
|
+
entity: CNAME ("." CNAME)+
|
|
130
|
+
|
|
131
|
+
// ---- Lexer ----
|
|
132
|
+
%import common.CNAME
|
|
133
|
+
%import common.WS
|
|
134
|
+
%import common.ESCAPED_STRING -> STRING
|
|
135
|
+
%import common.INT
|
|
136
|
+
%import common.SIGNED_NUMBER
|
|
137
|
+
LINE_COMMENT: /\/\/[^\n]*/
|
|
138
|
+
%ignore LINE_COMMENT
|
|
139
|
+
%ignore WS
|
hassl/parser/loader.py
ADDED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
hassl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
hassl/cli.py,sha256=
|
|
2
|
+
hassl/cli.py,sha256=yCtfMQHzKCmORDypwxtbGQywLvdERLo3BLYSC2WUxu8,1522
|
|
3
3
|
hassl/ast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
hassl/ast/nodes.py,sha256=HINbu3o_hEMDD5G9TgYeqAev-Af0Vacqc_gwQQnpiy0,762
|
|
5
5
|
hassl/codegen/__init__.py,sha256=NgEw86oHlsk7cQrHz8Ttrtp68Cm7WKceTWRr02SDfjo,854
|
|
@@ -7,13 +7,15 @@ hassl/codegen/package.py,sha256=9dcIjszhGXV26Hwr_rKHLz6yYbElyIegfhlXGi5Q0sY,1661
|
|
|
7
7
|
hassl/codegen/rules_min.py,sha256=2ko9bFRZujXw7lt5k8L6UbfmTwS2PCWfub5M6Lwkg4I,28330
|
|
8
8
|
hassl/codegen/yaml_emit.py,sha256=VTNnR_uvSSqsL7kX5NyXuPUZh5FK36a_sUFsRyrQOS8,2207
|
|
9
9
|
hassl/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
hassl/parser/hassl.lark,sha256=YIeY8ncd6nwBzS54A5JbvLhRiQd0u6ftea4nZac4_cA,3361
|
|
11
|
+
hassl/parser/loader.py,sha256=xwhdoMkmXskanY8IhqIOfkcOkkn33goDnsbjzS66FL8,249
|
|
10
12
|
hassl/parser/transform.py,sha256=dNTyPW9sOw09vBfvWMFSRRiTnOzZQWJvISV1o1aouD4,9481
|
|
11
13
|
hassl/semantics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
14
|
hassl/semantics/analyzer.py,sha256=1x2bAJXj8hsT_IBoxgfTFV0MmVMXcfjqzl_gWo-WuI8,5195
|
|
13
15
|
hassl/semantics/domains.py,sha256=-OuhA4RkOLVaLnBxhKfJFjiQMYBSTryX9KjHit_8ezI,308
|
|
14
|
-
hassl-0.2.
|
|
15
|
-
hassl-0.2.
|
|
16
|
-
hassl-0.2.
|
|
17
|
-
hassl-0.2.
|
|
18
|
-
hassl-0.2.
|
|
19
|
-
hassl-0.2.
|
|
16
|
+
hassl-0.2.1.dist-info/licenses/LICENSE,sha256=hPNSrn93Btl9sU4BkQlrIK1FpuFPvaemdW6-Scz-Xeo,1072
|
|
17
|
+
hassl-0.2.1.dist-info/METADATA,sha256=Z43GbkiT3Sy-Lx3O5eQv8iUdcadYiIx73xac624-sMU,4929
|
|
18
|
+
hassl-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
hassl-0.2.1.dist-info/entry_points.txt,sha256=qA8jYPZlESNL6V4fJCTPOBXFeEBtjLGGsftXsSo82so,42
|
|
20
|
+
hassl-0.2.1.dist-info/top_level.txt,sha256=BPuiULeikxMI3jDVLmv3_n7yjSD9Qrq58bp9af_HixI,6
|
|
21
|
+
hassl-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|