22
33# Modules
44import re
5+ import string
56from typing import Any
67
7- from .tokenizer import tokenize
8+ from .tokenizer import tokenize , block_ends , block_starts
9+
810from ..exceptions import InvalidSyntax
911from ..modules .simpleeval import simple_eval
1012
1113# Initialization
12- _format_regex = re .compile (r"\$\([^)]*\)" )
14+ _FORMAT_REGEX = re .compile (r"\$\([^)]*\)" )
15+ _NUMBER_START = string .digits + "+-"
1316
1417# Memory class
1518class Memory (object ):
@@ -37,27 +40,37 @@ def __repr__(self) -> str:
3740 return f"<DS value={ repr (self .value )} raw='{ self .raw } '>"
3841
3942 def _parse (self ) -> Any :
40- if not self .raw :
41- return
42-
43- # Check for expression groups
44- if self .raw [0 ] == "{" and self .raw [- 1 ] == "}" :
45- statement = self .raw .strip ("{}" ).strip ()
46- if statement .split (" " )[0 ] not in self .mem .interpreter .operators : # This is very hacky, to be rewritten
47- raise InvalidSyntax (
48- "bracket syntax can only store an operator statement" ,
49- 0 ,
50- self .mem .interpreter .stack
51- )
52-
53- return statement
54-
55- # Check for strings
56- if self .raw [0 ] in ["\" " , "'" , "(" ]:
57- if (self .raw [0 ] == "\" " and self .raw [- 1 ] == "\" " ) or \
58- (self .raw [0 ] == "'" and self .raw [- 1 ] == "'" ):
43+ if self .raw [0 ] not in block_starts :
44+ if self .raw [0 ] in _NUMBER_START :
45+ val = float (self .raw )
46+ if val .is_integer ():
47+ return int (val )
48+
49+ return val
50+
51+ # Handle variable
52+ self .refresh = self .refreshv
53+ return self .refresh ()
54+
55+ # Match statements
56+ if self .raw [- 1 ] != block_ends [block_starts .index (self .raw [0 ])]:
57+ raise InvalidSyntax ("open block was not closed" , len (self .raw ) - 1 , self .mem .interpreter .stack )
58+
59+ match self .raw [0 ]:
60+ case "{" :
61+ statement = self .raw [1 :][:- 1 ].strip ()
62+ if statement .split (" " )[0 ] not in self .mem .interpreter .operators :
63+ raise InvalidSyntax (
64+ "bracket syntax can only store a valid x++ expression" ,
65+ 0 ,
66+ self .mem .interpreter .stack
67+ )
68+
69+ return statement
70+
71+ case "\" " | "'" :
5972 value = self .raw [1 :][:- 1 ].replace ("\\ \" " , "\" " )
60- for item in re .findall (_format_regex , value ):
73+ for item in re .findall (_FORMAT_REGEX , value ):
6174 tokens , obj , reference = item [2 :][:- 1 ].split (" " ), None , False
6275 if len (tokens ) < 2 :
6376 obj = Datastore (self .mem , tokens [0 ])
@@ -68,7 +81,7 @@ def _parse(self) -> Any:
6881
6982 return value .encode ("latin-1" , "backslashreplace" ).decode ("unicode-escape" ) # String literal
7083
71- elif self . raw [ 0 ] == "(" and self . raw [ - 1 ] == ") " :
84+ case "( " :
7285 expr = self .raw [1 :][:- 1 ]
7386 if expr .split (" " )[0 ] not in self .mem .interpreter .operators :
7487 for token in tokenize (expr ):
@@ -84,18 +97,6 @@ def _parse(self) -> Any:
8497
8598 return self .mem .interpreter .execute (expr .replace ("\\ \" " , "\" " ))
8699
87- # Check for ints/floats
88- if self .raw [0 ].isdigit () or self .raw [0 ] in "+-" :
89- val = float (self .raw )
90- if val .is_integer ():
91- return int (val )
92-
93- return val
94-
95- # Handle variable
96- self .refresh = self .refreshv
97- return self .refresh ()
98-
99100 def set (self , value : Any ) -> None :
100101 self .store [self .id_ ] = value
101102 self .value = value
0 commit comments