Skip to content

Commit e9c771c

Browse files
committed
ENH: caret, more negation rules
1 parent 99d7190 commit e9c771c

File tree

7 files changed

+53
-9
lines changed

7 files changed

+53
-9
lines changed

src/latform/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
STATEMENT_NAME_EQUALS = Delimiter("=", role=Role.statement_definition)
1111

1212
AMPERSAND = Delimiter("&")
13+
CARET = Delimiter("^")
1314
COLON = Delimiter(":")
1415
COMMA = Delimiter(",")
1516
DQUOTE = Delimiter('"')

src/latform/output.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ def _needs_space_before(parts: list[Token], idx: int) -> tuple[bool, str]:
101101
return False, "no space around /"
102102
if prev == "*" or cur == "*":
103103
return False, "no space around *"
104+
if cur == "^":
105+
return False, "no space around caret"
104106
if cur == "-":
105107
if prev in close_brackets:
106108
return True, "space before minus:- after closing bracket"

src/latform/parser.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import os
43
import pathlib
54
import sys
65
from dataclasses import dataclass, field
@@ -19,6 +18,7 @@
1918
Parameter,
2019
Simple,
2120
Statement,
21+
get_call_filename,
2222
)
2323
from .token import Comments
2424
from .tokenizer import tokenize
@@ -384,18 +384,15 @@ def parse(self):
384384
self.by_filename[parent_fn] = statements
385385
for st in statements:
386386
if isinstance(st, Simple) and st.statement == "call":
387-
attr = st.get_named_attribute("filename", partial_match=True)
388-
389-
sub_filename = (
390-
attr.value if isinstance(attr.value, Token) else attr.value.to_token()
391-
).remove_quotes()
392-
fn = parent_fn.parent / os.path.expandvars(sub_filename)
387+
sub_filename, fn = get_call_filename(
388+
st, caller_filename=parent_fn, expand_vars=True
389+
)
393390
self.local_file_to_source_filename[sub_filename] = fn
394391
self.stack.append(fn)
395392
parent_fn = pathlib.Path(filename)
396393
return self.by_filename
397394

398-
def reformat(self, options: FormatOptions) -> None:
395+
def reformat(self, options: FormatOptions, *, dest: pathlib.Path | None = None) -> None:
399396
from .output import format_statements
400397

401398
for fn, statements in self.by_filename.items():

src/latform/statements.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import os.path
4+
import pathlib
35
from dataclasses import dataclass, field
46
from typing import ClassVar
57

@@ -232,3 +234,27 @@ def to_output_nodes(self):
232234
*comma_delimit(self.attributes),
233235
]
234236
return [self.name, STATEMENT_NAME_COLON, *comma_delimit([self.keyword, *self.attributes])]
237+
238+
239+
def get_call_filename(
240+
st: Simple,
241+
*,
242+
caller_filename: pathlib.Path | None + None,
243+
expand_vars: bool = True,
244+
) -> tuple[str, pathlib.Path]:
245+
if not isinstance(st, Simple):
246+
raise ValueError(f"Unexpected type: {type(st).__name__}")
247+
248+
if st.statement != "call":
249+
raise ValueError(f"Statement is not 'call': {st.statement}")
250+
251+
attr = st.get_named_attribute("filename", partial_match=True)
252+
253+
sub_filename = (
254+
attr.value if isinstance(attr.value, Token) else attr.value.to_token()
255+
).remove_quotes()
256+
expanded = os.path.expandvars(sub_filename) if expand_vars else sub_filename
257+
258+
if not caller_filename:
259+
return sub_filename, pathlib.Path(expanded)
260+
return sub_filename, caller_filename.parent / expanded

src/latform/tests/test_output.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,21 @@ def test_format_element_from_source(code: str, expected: str) -> None:
374374
"b01w[rho]/b01w[L]",
375375
id="array_indexing_division",
376376
),
377+
pytest.param(
378+
"b01w[ rho ] ^3",
379+
"b01w[rho]^3",
380+
id="exp_after_bracket",
381+
),
382+
pytest.param(
383+
"sqrt(foo) ^3",
384+
"sqrt(foo)^3",
385+
id="exp_after_func",
386+
),
387+
pytest.param(
388+
"1.3e4 ^ 4",
389+
"1.3e4^4",
390+
id="exp_after_sci_not",
391+
),
377392
pytest.param(
378393
"ename[frequencies(1)%amp]",
379394
"ename[frequencies(1)%amp]",

src/latform/token.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ def __eq__(self, other) -> bool:
6969

7070
return case_insensitive_equality
7171

72+
def __ne__(self, other) -> bool:
73+
return not (self == other)
74+
7275
@property
7376
def is_quoted_string(self) -> bool:
7477
return (self.startswith(_SQUOTE) and self.endswith(_SQUOTE)) or (

src/latform/tokenizer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class _StatementTokenBlock:
1919
lineno: int
2020
items: list[Token | Delimiter] = field(default_factory=list)
2121

22-
def stack(self):
22+
def stack(self) -> Block:
2323
root = Block()
2424
stack = [root]
2525
delim_state = DelimiterState()

0 commit comments

Comments
 (0)