Class: Expressir::Express::Parser::Parser
- Inherits:
-
Parsanol::Parser
- Object
- Parsanol::Parser
- Expressir::Express::Parser::Parser
- Defined in:
- lib/expressir/express/parser.rb
Constant Summary collapse
- LARGE_FILE_THRESHOLD =
Threshold for using memory-bounded fresh parse (bytes) Files above this use parse_fresh which has no packrat cache
1024 * 1024
- KEYWORDS =
%i[ ABS ABSTRACT ACOS AGGREGATE ALIAS AND ANDOR ARRAY AS ASIN ATAN BAG BASED_ON BEGIN BINARY BLENGTH BOOLEAN BY CASE CONSTANT CONST_E COS DERIVE DIV ELSE END END_ALIAS END_CASE END_CONSTANT END_ENTITY END_FUNCTION END_IF END_LOCAL END_PROCEDURE END_REPEAT END_RULE END_SCHEMA END_SUBTYPE_CONSTRAINT END_TYPE ENTITY ENUMERATION ESCAPE EXISTS EXP EXTENSIBLE FALSE FIXED FOR FORMAT FROM FUNCTION GENERIC GENERIC_ENTITY HIBOUND HIINDEX IF IN INSERT INTEGER INVERSE LENGTH LIKE LIST LOBOUND LOCAL LOG LOG10 LOG2 LOGICAL LOINDEX MOD NOT NUMBER NVL ODD OF ONEOF OPTIONAL OR OTHERWISE PI PROCEDURE QUERY REAL REFERENCE REMOVE RENAMED REPEAT RETURN ROLESOF RULE SCHEMA SELECT SELF SET SIN SIZEOF SKIP SQRT STRING SUBTYPE SUBTYPE_CONSTRAINT SUPERTYPE TAN THEN TO TRUE TYPE TYPEOF TOTAL_OVER UNIQUE UNKNOWN UNTIL USE USEDIN VALUE VALUE_IN VALUE_UNIQUE VAR WITH WHERE WHILE XOR ].freeze
- @@cached_grammar_json =
Cache for native parser grammar (class-level)
nil- @@cached_grammar_atom_id =
nil- @@cached_parser =
Cache for parser instance (avoids ~7ms overhead of Parser.new)
nil- @@parser_mutex =
Mutex.new
- @@cached_schema_grammar_json =
Cache for schemaDecl grammar JSON (used for streaming parse)
nil
Class Method Summary collapse
-
.cached_grammar_json ⇒ Object
Get cached grammar JSON for native parsing.
-
.cached_parser ⇒ Object
Get cached parser instance (thread-safe) Reusing the parser avoids the overhead of reinitializing all rule definitions.
-
.cached_schema_grammar_json ⇒ Object
Get cached grammar JSON for schemaDecl (used for streaming parse).
-
.clear_parser_cache ⇒ Object
Clear the cached parser (useful for testing or after grammar changes).
-
.native_available? ⇒ Boolean
Check if native parsing is available.
-
.parse_native(source) ⇒ Hash, Array
Parse using native engine with Rust-side transformation (fastest).
Instance Method Summary collapse
Class Method Details
.cached_grammar_json ⇒ Object
Get cached grammar JSON for native parsing
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/expressir/express/parser.rb', line 54 def self.cached_grammar_json return @@cached_grammar_json if @@cached_grammar_json parser = new atom = parser.syntax # Cache by atom object_id if atom.object_id != @@cached_grammar_atom_id @@cached_grammar_atom_id = atom.object_id @@cached_grammar_json = Parsanol::Native.serialize_grammar(atom) end @@cached_grammar_json end |
.cached_parser ⇒ Object
Get cached parser instance (thread-safe) Reusing the parser avoids the overhead of reinitializing all rule definitions
26 27 28 29 30 31 32 |
# File 'lib/expressir/express/parser.rb', line 26 def self.cached_parser return @@cached_parser if @@cached_parser @@parser_mutex.synchronize do @@cached_parser ||= new end end |
.cached_schema_grammar_json ⇒ Object
Get cached grammar JSON for schemaDecl (used for streaming parse)
70 71 72 73 74 75 76 |
# File 'lib/expressir/express/parser.rb', line 70 def self.cached_schema_grammar_json return @@cached_schema_grammar_json if @@cached_schema_grammar_json schema_atom = cached_parser.schemaDecl @@cached_schema_grammar_json = Parsanol::Native.serialize_grammar(schema_atom) @@cached_schema_grammar_json end |
.clear_parser_cache ⇒ Object
Clear the cached parser (useful for testing or after grammar changes)
35 36 37 38 39 |
# File 'lib/expressir/express/parser.rb', line 35 def self.clear_parser_cache @@parser_mutex.synchronize do @@cached_parser = nil end end |
.native_available? ⇒ Boolean
Check if native parsing is available
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/expressir/express/parser.rb', line 42 def self.native_available? return @native_available unless @native_available.nil? @native_available = begin require "parsanol/native" Parsanol::Native.available? rescue LoadError false end end |
.parse_native(source) ⇒ Hash, Array
Parse using native engine with Rust-side transformation (fastest)
This method provides ~17x speedup over pure Ruby parsing. The transformation happens in Rust using to_parslet_compatible, producing Parslet-compatible output that Builder.build can consume directly.
87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/expressir/express/parser.rb', line 87 def self.parse_native(source) unless native_available? raise LoadError, "Native parser not available" end grammar_atom = cached_parser.syntax # Use fresh-parse (no cache) for large files to bound memory if source.bytesize > LARGE_FILE_THRESHOLD Parsanol::Native.parse_fresh(grammar_atom, source) else Parsanol::Native.parse(grammar_atom, source) end end |
Instance Method Details
#cstr(atom) ⇒ Object
105 106 107 |
# File 'lib/expressir/express/parser.rb', line 105 def cstr(atom) cts(str(atom).as(:str)) end |
#cts(atom) ⇒ Object
101 102 103 |
# File 'lib/expressir/express/parser.rb', line 101 def cts(atom) spaces >> atom end |
#keyword_rule(str) ⇒ Object
125 126 127 128 129 130 |
# File 'lib/expressir/express/parser.rb', line 125 def keyword_rule(str) key_chars = str.to_s.chars key_chars .collect! { |char| match("[#{char}#{char.downcase}]") } .reduce(:>>) >> match["a-zA-Z0-9_"].absent? end |