@@ -327,10 +327,14 @@ def parse(
327327 with_progress = False ,
328328 with_tree = True ,
329329 with_header = False ,
330+ only_header = False
330331):
331332 if filename :
332333 assert not filecontent
333334 filecontent = builtins .open (filename , encoding = None ).read ()
335+
336+ if only_header :
337+ assert with_header , "'only_header=True' requires 'with_header=True'"
334338
335339 # Match and remove the comments
336340 p = r"/\*[\s\S]*?\*/"
@@ -339,6 +343,37 @@ def replace_fn(match):
339343 return re .sub (r"[^\n]" , " " , match .group (), flags = re .M )
340344
341345 filecontent_wo_comments = re .sub (p , replace_fn , filecontent )
346+
347+
348+ if only_header :
349+ # Extract just the HEADER section using regex
350+ header_match = re .search (
351+ r"ISO-10303-21;\s*HEADER;(.*?)ENDSEC;" ,
352+ filecontent_wo_comments ,
353+ flags = re .DOTALL | re .IGNORECASE ,
354+ )
355+ if not header_match :
356+ raise ValidationError ("No HEADER section found in file" )
357+
358+ header_text = f"HEADER;{ header_match .group (1 )} ENDSEC;"
359+ full_header_text = f"ISO-10303-21;{ header_text } DATA;ENDSEC;END-ISO-10303-21;"
360+
361+ parser = Lark (grammar , parser = "lalr" , start = "file" )
362+ try :
363+ ast = parser .parse (full_header_text )
364+ except (UnexpectedToken , UnexpectedCharacters ) as e :
365+ raise SyntaxError (filecontent , e )
366+
367+ header_tree = ast .children [0 ] # HEADER section
368+
369+ def make_header_ent (ast ):
370+ kw , param_list = ast .children
371+ kw = kw .children [0 ].value
372+ return kw , T (visit_tokens = True ).transform (param_list )
373+
374+ header = dict (map (make_header_ent , header_tree .children [0 ].children ))
375+ return header
376+
342377
343378 instance_identifiers = []
344379 transformer = {}
@@ -483,5 +518,20 @@ def by_type(self, type: str) -> list[entity_instance]:
483518 )
484519
485520
486- def open (fn ) -> file :
487- return file (parse (filename = fn , with_tree = True , with_header = True ))
521+ def open (fn , only_header : bool = False ) -> file :
522+ if only_header : # Ensure consistent options
523+ parse_outcomes = parse (
524+ filename = fn ,
525+ with_tree = True ,
526+ with_header = True , # must be True to return the header
527+ only_header = True ,
528+ )
529+ return file ((parse_outcomes , defaultdict (list ))) # data section is empty
530+ else :
531+ parse_outcomes = parse (
532+ filename = fn ,
533+ with_tree = True ,
534+ with_header = True ,
535+ only_header = False ,
536+ )
537+ return file (parse_outcomes )
0 commit comments