66import cedarscript_grammar
77from dataclasses import dataclass
88
9+
910class ParseError (NamedTuple ):
1011 command_ordinal : int
1112 message : str
@@ -14,10 +15,13 @@ class ParseError(NamedTuple):
1415 suggestion : str
1516
1617 def __str__ (self ):
18+ line_msg = f'; LINE #{ self .line } ' if self .line else ''
19+ col_msg = f'; COLUMN #{ self .column } ' if self .column else ''
20+ suggestion_msg = f'{ self .suggestion } ' if self .suggestion else ''
1721 return (
18- f"<error-details><error-location>COMMAND #{ self .command_ordinal } { f'; LINE # { self . line } ' if self . line else '' } { f'; COLUMN # { self . column } ' if self . column else '' } </error-location>"
22+ f"<error-details><error-location>COMMAND #{ self .command_ordinal } { line_msg } { col_msg } </error-location>"
1923 f"<type>PARSING (no commands were applied at all)</type><description>{ self .message } </description>"
20- f"<suggestion>{ f" { self . suggestion } " if self . suggestion else "" } "
24+ f"<suggestion>{ suggestion_msg } "
2125 "(NEVER apologize; just take a deep breath, re-read grammar rules (enclosed by <grammar.js> tags) "
2226 "and fix you CEDARScript syntax)</suggestion></error-details>"
2327 )
@@ -39,6 +43,7 @@ class MarkerCompatible:
3943 def as_marker (self ) -> 'Marker' :
4044 pass
4145
46+
4247@dataclass
4348class Marker (MarkerCompatible ):
4449 type : MarkerType
@@ -69,7 +74,7 @@ def __str__(self):
6974 case RelativePositionType .AT :
7075 pass
7176 case _:
72- result = f'{ result } ({ self .qualifier .replace ('_' , ' ' )} )'
77+ result = f'{ result } ({ str ( self .qualifier ) .replace ('_' , ' ' )} )'
7378 return result
7479
7580
@@ -112,7 +117,7 @@ def as_marker(self) -> Marker:
112117 return Marker (self .identifier_type , self .where_clause .value , self .offset )
113118
114119 def __str__ (self ):
115- result = f"{ self .identifier_type .lower ()} ({ self .where_clause } )"
120+ result = f"{ str ( self .identifier_type ) .lower ()} ({ self .where_clause } )"
116121 if self .offset is not None :
117122 result += f" at offset { self .offset } "
118123 return f"{ result } from file { self .file_path } "
@@ -188,6 +193,7 @@ def files_to_change(self) -> tuple[str, ...]:
188193class CreateCommand (FileCommand ):
189194 content : str
190195
196+
191197@dataclass
192198class RmFileCommand (FileCommand ):
193199 pass
@@ -423,8 +429,10 @@ def parse_where_clause(self, node):
423429 return WhereClause (field = field , operator = operator , value = value )
424430
425431 def parse_update_action (self , node ):
426- child_types = ['update_delete_region_clause' , 'update_delete_mos_clause' , 'update_move_region_clause' , 'update_move_mos_clause' ,
427- 'insert_clause' , 'replace_mos_clause' , 'replace_region_clause' ]
432+ child_types = [
433+ 'update_delete_region_clause' , 'update_delete_mos_clause' , 'update_move_region_clause' ,
434+ 'update_move_mos_clause' , 'insert_clause' , 'replace_mos_clause' , 'replace_region_clause'
435+ ]
428436 action_node = self .find_first_by_type (node .named_children , child_types )
429437 if action_node is None :
430438 raise ValueError ("No valid action found in update command" )
@@ -525,7 +533,7 @@ def parse_offset_clause(self, node):
525533 return None
526534 return int (self .find_first_by_type (node .children , 'number' ).text )
527535
528- def parse_relative_indentation (self , node ) -> int :
536+ def parse_relative_indentation (self , node ) -> int | None :
529537 node = self .find_first_by_type (node .named_children , 'relative_indentation' )
530538 if node is None :
531539 return None
@@ -537,13 +545,12 @@ def parse_content(self, node) -> str | tuple[Region, int | None]:
537545 return None
538546 match content .type :
539547 case 'content_clause' :
540- return self .parse_content_clause (content ) # str
548+ return self .parse_content_clause (content ) # str
541549 case 'content_from_segment' :
542- return self .parse_content_from_segment_clause (content ) # tuple[Region, int]
550+ return self .parse_content_from_segment_clause (content ) # tuple[Region, int]
543551 case _:
544552 raise ValueError (f"Invalid content type: { content .type } " )
545553
546-
547554 def parse_singlefile_clause (self , node ):
548555 if node is None or node .type != 'singlefile_clause' :
549556 raise ValueError ("Expected singlefile_clause node" )
@@ -581,7 +588,8 @@ def parse_to_value_clause(self, node):
581588 raise ValueError ("No value found in to_value_clause" )
582589 return self .parse_string (value_node )
583590
584- def parse_string (self , node ):
591+ @staticmethod
592+ def parse_string (node ):
585593 match node .type .casefold ():
586594 case 'string' :
587595 node = node .named_children [0 ]
@@ -596,7 +604,8 @@ def parse_string(self, node):
596604
597605 return text
598606
599- def parse_multiline_string (self , node ):
607+ @staticmethod
608+ def parse_multiline_string (node ):
600609 return node .text .decode ('utf8' ).strip ("'''" ).strip ('"""' )
601610
602611 def parse_relative_indent_block (self , node ) -> str :
@@ -610,7 +619,8 @@ def parse_relative_indent_block(self, node) -> str:
610619 lines .append (f"{ ' ' * (4 * indent )} { content .text } " )
611620 return '\n ' .join (lines )
612621
613- def find_first_by_type (self , nodes : Sequence [any ], child_type ):
622+ @staticmethod
623+ def find_first_by_type (nodes : Sequence [any ], child_type ):
614624 if isinstance (child_type , list ):
615625 for child in nodes :
616626 if child .type in child_type :
@@ -621,7 +631,8 @@ def find_first_by_type(self, nodes: Sequence[any], child_type):
621631 return child
622632 return None
623633
624- def find_first_by_field_name (self , node : any , field_names ):
634+ @staticmethod
635+ def find_first_by_field_name (node : any , field_names ):
625636 if not isinstance (field_names , list ):
626637 return node .child_by_field_name (field_names )
627638
0 commit comments