the benchmarking code looks like this:
@inline(never)
static
func benchmarkSwiftJSON(_ json:[UInt8]) throws -> Int
{
try Grammar.parse(json, as: JSON.Rule<Int>.Root.self,
in: [JSON].self).count
}
which calls into this swift-grammar function:
extension Grammar
{
@inlinable public static
func parse<Source, Rule, Vector>(_ source:Source, as _:Rule.Type, in _:Vector.Type) throws -> Vector
where Source:Collection, Rule:ParsingRule,
Rule.Location == Source.Index, Rule.Terminal == Source.Element,
Vector:RangeReplaceableCollection, Vector.Element == Rule.Construction
{
var input:ParsingInput<NoDiagnostics<Source>> = .init(source)
let construction:Vector = input.parse(as: Rule.self, in: Vector.self)
try input.parse(as: End<Rule.Location, Rule.Terminal>.self)
return construction
}
}
which calls into this swift-grammar API:
extension ParsingInput
{
@inlinable public mutating
func parse<Rule>(as _:Rule?.Type) -> Rule.Construction?
where Rule:ParsingRule, Rule.Location == Diagnostics.Source.Index, Rule.Terminal == Diagnostics.Source.Element
{
try? self.parse(as: Rule.self)
}
@inlinable public mutating
func parse<Rule, Vector>(as _:Rule.Type, in _:Vector.Type) -> Vector
where Rule:ParsingRule, Rule.Location == Diagnostics.Source.Index, Rule.Terminal == Diagnostics.Source.Element,
Rule.Construction == Vector.Element,
Vector:RangeReplaceableCollection
{
var vector:Vector = .init()
while let element:Rule.Construction = self.parse(as: Rule?.self)
{
vector.append(element)
}
return vector
}
}
which finally calls this swift-grammar API,
extension ParsingInput
{
@inlinable public mutating
func group<Rule, Construction>(_:Rule.Type, _ body:(inout Self) throws -> Construction)
throws -> Construction
{
let breadcrumb:Diagnostics.Breadcrumb =
self.diagnostics.push(index: self.index, for: Construction.self, by: Rule.self)
do
{
let construction:Construction = try body(&self)
self.diagnostics.pop()
return construction
}
catch var error
{
self.diagnostics.reset(index: &self.index, to: breadcrumb, because: &error)
throw error
}
}
@inlinable public mutating
func parse<Rule>(as _:Rule.Type) throws -> Rule.Construction
where Rule:ParsingRule, Rule.Location == Diagnostics.Source.Index, Rule.Terminal == Diagnostics.Source.Element
{
try self.group(Rule.self){ try Rule.parse(&$0) }
}
}
which ultimately calls JSON.Rule<Location>.parse(_:)/JSON.Rule<Location>.Root.parse(_:).
here is the definition of NoDiagnostics:
@frozen public
struct NoDiagnostics<Source>:ParsingDiagnostics where Source:Collection
{
@inlinable public
init()
{
}
// force inlining because these functions ignore most of their inputs, and
// don’t contain many instructions (if any)
@inline(__always)
@inlinable public
func push<Rule, Construction>(index:Source.Index, for _:Construction.Type, by _:Rule.Type)
-> Source.Index
{
index
}
@inline(__always)
@inlinable public
func pop()
{
}
@inline(__always)
@inlinable public
func reset(index:inout Source.Index, to breadcrumb:Source.Index, because _:inout Error)
{
index = breadcrumb
}
}