Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion interscript.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ Gem::Specification.new do |spec|
spec.add_dependency "thor"
spec.add_dependency "interscript-maps", "~> #{Interscript::VERSION.split(".")[0, 2].join(".")}.0a"
spec.add_dependency "text"
spec.add_dependency "parslet", "~> 2.0"
spec.add_dependency "parsanol", "~> 1.3"
end
2 changes: 1 addition & 1 deletion lib/interscript/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Interscript::Compiler

def self.call(map, **kwargs)
# DSL.parse locates, dispatches .isc and caches the parsed document —
# calling parse_isc here re-ran a ~30 s Parslet parse on every
# calling parse_isc here re-ran a full grammar parse on every
# compiler instantiation.
map = Interscript::DSL.parse(map) if String === map
compiler = new
Expand Down
2 changes: 1 addition & 1 deletion lib/interscript/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def self.parse(map_name, reverse: true)
end
end
# ISC documents route through the ISC parser, not the .imp DSL.
# The parse is expensive (Parslet over the whole map) — cache it like
# The parse is expensive (the whole grammar over the map) — cache it like
# the .imp path does, or every transliterate call re-parses the map.
return @cache[map_name] = Interscript::Compiler.parse_isc(path) if path.end_with?(".isc")

Expand Down
2 changes: 1 addition & 1 deletion lib/interscript/isc.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
Expand Down
18 changes: 11 additions & 7 deletions lib/interscript/isc/document_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ def build
def unquote(fragment)
return "" if fragment.nil?
return fragment.to_s unless fragment.is_a?(Hash)
return fragment.to_s unless fragment.key?(:string)
# Direct decode for the overwhelmingly common shape — routing
# every quoted string through Transform pattern matching
# dominated large-map builds.
return Transform.decode_string_parts(fragment[:string]) if fragment.key?(:string)

out = @transform.apply(fragment)
out.is_a?(Items::StringValue) ? out.value : out.to_s
fragment.to_s
end

def unescape_braces(text)
Expand Down Expand Up @@ -325,17 +327,19 @@ def extract_dependency(item)
}.compact
end

# Convert a parslet tree fragment into a concrete Item object via Transform.
# Convert a grammar tree fragment into a concrete Item object via
# Transform. Reuses the builder's Transform instance — allocating
# one per fragment dominated large-map builds.
def materialize(fragment)
case fragment
when Hash
if fragment.key?(:concatenation)
Transform.new.apply(fragment)
@transform.apply(fragment)
else
Transform.new.apply(concatenation: [fragment])
@transform.apply(concatenation: [fragment])
end
when Array
Transform.new.apply(concatenation: fragment)
@transform.apply(concatenation: fragment)
when NilClass
Items::None.new
else
Expand Down
2 changes: 1 addition & 1 deletion lib/interscript/isc/grammar.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/aliases.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Aliases block: named expressions reused throughout the system.
module Aliases
include Parslet
include Parsanol

rule(:aliases_block) do
str("aliases") >> whitespace? >>
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/dependencies.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Dependencies: references to other systems whose stages may be invoked.
module Dependencies
include Parslet
include Parsanol

rule(:dependency_decl) do
str("dependency") >> whitespace >>
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/items.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Item expressions: the building blocks of rule matches and targets.
module Items
include Parslet
include Parsanol

rule(:item_atom) do
quoted_string |
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/metadata.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Metadata block: identity + provenance + lifecycle of a system.
module Metadata
include Parslet
include Parsanol

rule(:metadata_block) do
str("metadata") >> whitespace? >>
Expand Down
13 changes: 10 additions & 3 deletions lib/interscript/isc/grammar/concerns/primitives.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
Expand All @@ -9,7 +9,7 @@ module Concerns
# Lexical primitives shared by every other concern.
# Mirrors the structure of LutaML LML's Concerns::Primitives.
module Primitives
include Parslet
include Parsanol

# -- Whitespace and comments

Expand Down Expand Up @@ -74,9 +74,16 @@ module Primitives
end

# Double-quoted strings: \\uXXXX, \\n, etc. are interpreted.
# Escape-free stretches are captured as ONE run slice — a
# per-char capture allocates a hash + slice per character
# (~700k nodes for a large map) and the Transform pattern
# match grinds on them even under the native parse engine.
rule(:plain_run) do
(str("\\") | str('"')).absent? >> any
end
rule(:double_quoted_string) do
str('"') >>
(escape_sequence | (str('"').absent? >> any).as(:char)).repeat.as(:string) >>
(escape_sequence | plain_run.repeat(1).as(:run)).repeat.as(:string) >>
str('"')
end

Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/stages.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Stages: ordered transformation pipelines.
module Stages
include Parslet
include Parsanol

rule(:stage_block) do
str("stage") >>
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/system.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Top-level system block.
module System
include Parslet
include Parsanol

# A block-item is any of the top-level constructs that may appear
# inside `system "<code>" { ... }`.
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/concerns/tests.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
module Concerns
# Tests block: normative input/output pairs.
module Tests
include Parslet
include Parsanol

rule(:tests_block) do
str("tests") >> whitespace? >>
Expand Down
4 changes: 2 additions & 2 deletions lib/interscript/isc/grammar/core.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
module Grammar
# Core grammar: composes every concern into a single Parser ancestor.
# Mirrors the structure of LutaML LML's Grammar::Core.
module Core
include Parslet
include Parsanol
include Concerns::Primitives
include Concerns::Items
include Concerns::Metadata
Expand Down
6 changes: 3 additions & 3 deletions lib/interscript/isc/parser.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
Expand All @@ -11,7 +11,7 @@ module Isc
#
# The returned tree is a parslet-shaped hash — lists of hashes with
# symbol keys. Convert to a domain object via Interscript::Isc::DocumentBuilder.
class Parser < Parslet::Parser
class Parser < Parsanol::Parser
include Grammar::Core

root :isc_source
Expand All @@ -22,7 +22,7 @@ def self.parse(source, filename: nil)

def parse_with_callbacks(source, filename: nil)
Normalizer.normalize(parse(source))
rescue Parslet::ParseFailed => e
rescue Parsanol::ParseFailed => e
raise ParseError.new(e.message, filename: filename, source: source, cause: e)
end
end
Expand Down
12 changes: 6 additions & 6 deletions lib/interscript/isc/transform.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require "parslet"
require "parsanol"

module Interscript
module Isc
Expand All @@ -9,7 +9,7 @@ module Isc
#
# String escapes are unescaped here. Items are flattened. Constraints
# are tagged by kind.
class Transform < Parslet::Transform
class Transform < Parsanol::Transform
# String atom: parslet gives us a parslet slice for simple strings,
# or an array of pieces (escape-sequence fragments interleaved with
# raw chars) for strings containing escapes. Flatten both to a single
Expand All @@ -18,7 +18,7 @@ class Transform < Parslet::Transform
rule(string: sequence(:parts)) do
Items::StringValue.new(Transform.decode_string_parts(parts))
end
rule(char: simple(:c)) { c.to_s }
rule(run: simple(:s)) { s.to_s }

rule(identifier: simple(:i)) { i.to_s }

Expand Down Expand Up @@ -52,13 +52,13 @@ class Transform < Parslet::Transform

# Shared decoder for the pieces of a :string capture — used by the
# transform rules above and by the Normalizer's scalar folding. A
# fragment without an escape key is a raw character slice.
# fragment without an escape key is a raw run slice.
def self.decode_string_parts(parts)
Array(parts).map do |p|
case p
when Hash
if p.key?(:char)
p[:char].to_s
if p.key?(:run)
p[:run].to_s
elsif p.key?(:newline)
"\n"
elsif p.key?(:carriage_return)
Expand Down
Loading