11""" A private module to parse multivector expressions """
22import re
3+ from typing import List
34
4- op_cntrct = re .compile (r'(([A-Za-z0-9\_\#]+)(\||<|>)([A-Za-z0-9\_\#]+))' )
5- op_wedge = re .compile (r'(([A-Za-z0-9\_\#]+)[\^]{1}([A-Za-z0-9\_\#]+)([\^]{1}([A-Za-z0-9\_\#]+))*)' )
6- ops = r'[\^\|\<\>]+'
7- ops_search = re .compile (r'(\^|\||<|>)+' )
8- parse_paren_calls = 0
9- op_dict = {}
10- op_lst = []
115
12- OPS = { '<>|' : r'(([A-Za-z0-9\_\#]+)(\||<|>)([A-Za-z0-9\_\#]+))' ,
13- '^' : r'(([A-Za-z0-9\_\#]+)[\^]{1}([A-Za-z0-9\_\#]+)([\^]{1}([A-Za-z0-9\_\#]+))*)' ,
14- '*' : r'(( [A-Za-z0-9\_\#]+)[\*]{1}([A-Za-z0-9\_\#]+)([\*]{1}([A-Za-z0-9\_\#]+))*)' }
6+ # The `#` character is included because we generate tokens containing it in
7+ # _parse_paren.
8+ _operand_re = r"( [A-Za-z0-9\_\#]+)"
159
16-
17- def set_precedence (op_ord : str = '<>|,^,*' ) -> None :
18- global op_dict , op_lst
19- op_lst = op_ord .split (',' )
20- op_dict = {}
21- for op in op_lst :
22- op_dict [op ] = re .compile (OPS [op ])
10+ _operator_res = {
11+ '<>|' : re .compile (r'(ARG(\||<|>)ARG)' .replace ('ARG' , _operand_re )),
12+ '^' : re .compile (r'(ARG[\^]ARG([\^]ARG)*)' .replace ('ARG' , _operand_re )),
13+ '*' : re .compile (r'(ARG[\*]ARG([\*]ARG)*)' .replace ('ARG' , _operand_re )),
14+ }
2315
2416
2517def _contains_interval (interval1 , interval2 ): # interval1 inside interval2
@@ -29,9 +21,13 @@ def _contains_interval(interval1, interval2): # interval1 inside interval2
2921 return False
3022
3123
24+ # counter to generate unique tokens
25+ _parse_paren_calls = 0
26+
27+
3228def _parse_paren (line ):
33- global parse_paren_calls
34- parse_paren_calls += 1
29+ global _parse_paren_calls
30+ _parse_paren_calls += 1
3531
3632 if ('(' not in line ) or (')' not in line ):
3733 return [[[line ]]]
@@ -82,7 +78,7 @@ def _parse_paren(line):
8278 for level in level_lst [1 :]:
8379 igroup = 0
8480 for group in level :
85- token = '#' + str (parse_paren_calls ) + '_' + str (ilevel ) + '_' + str (igroup ) + '#'
81+ token = '#' + str (_parse_paren_calls ) + '_' + str (ilevel ) + '_' + str (igroup ) + '#'
8682 level_lst [ilevel ][igroup ].append (line [group [0 ]:group [1 ] + 1 ])
8783 level_lst [ilevel ][igroup ].append (token )
8884 igroup += 1
@@ -150,17 +146,21 @@ def _add_paren(line, re_exprs):
150146 return line
151147
152148
153- def parse_line (line : str ) -> str :
154- global op_lst , op_dict
149+ def validate_op_order (op_order : List [str ]) -> None :
150+ if not all (op in _operator_res for op in op_order ):
151+ raise ValueError ("Illegal operator" )
152+
153+
154+ def parse_line (line : str , op_order : List [str ]) -> str :
155155 line = line .replace (' ' , '' )
156156 level_lst = _parse_paren (line )
157157 ilevel = 0
158158 for level in level_lst :
159159 igroup = 0
160160 for group in level :
161161 string = group [- 1 ]
162- for op in op_lst :
163- string = _add_paren (string , op_dict [op ])
162+ for op in op_order :
163+ string = _add_paren (string , _operator_res [op ])
164164 level_lst [ilevel ][igroup ][- 1 ] = string
165165 igroup += 1
166166 ilevel += 1
0 commit comments