@@ -16,14 +16,50 @@ class Parser < Parsanol::Parser
1616
1717 root :isc_source
1818
19- def self . parse ( source , filename : nil )
20- new . parse_with_callbacks ( source , filename : filename )
21- end
19+ # The compiled grammar, shipped alongside the .parg source; the
20+ # runtime parses through it when parsanol carries PARG (>= 1.3.61)
21+ # and falls back to the Ruby-DSL grammar otherwise. Trees are
22+ # byte-identical by the corpus gate in the parg_diff spec.
23+ ARTIFACT_PATH = File . expand_path ( "grammar/isc.artifact.json" , __dir__ )
24+
25+ class ArtifactUnavailable < StandardError ; end
26+
27+ class << self
28+ def parse ( source , filename : nil )
29+ parse_with_callbacks ( source , filename : filename )
30+ end
31+
32+ def parse_with_callbacks ( source , filename : nil )
33+ tree = begin
34+ parse_with_artifact ( source )
35+ rescue ArtifactUnavailable
36+ parse_with_dsl ( source )
37+ end
38+ Normalizer . normalize ( tree )
39+ rescue Parsanol ::ParseFailed => e
40+ raise ParseError . new ( e . message , filename : filename , source : source , cause : e )
41+ end
42+
43+ def parse_with_artifact ( source )
44+ artifact . parse ( "isc" , source )
45+ end
46+
47+ def parse_with_dsl ( source )
48+ new . parse ( source )
49+ end
50+
51+ def artifact
52+ @artifact ||= begin
53+ require "parsanol/parg"
54+ Parsanol ::PARG ::Artifact . load ( ARTIFACT_PATH )
55+ rescue LoadError , StandardError => e
56+ raise ArtifactUnavailable , "parg artifact unavailable: #{ e . class } : #{ e . message } "
57+ end
58+ end
2259
23- def parse_with_callbacks ( source , filename : nil )
24- Normalizer . normalize ( parse ( source ) )
25- rescue Parsanol ::ParseFailed => e
26- raise ParseError . new ( e . message , filename : filename , source : source , cause : e )
60+ def reset_artifact
61+ @artifact = nil
62+ end
2763 end
2864 end
2965
0 commit comments