Skip to content

Linter reference

The AsciiChem linter is a separate opt-in pass that walks the model and reports chemistry errors. It does not modify the model.

formula = AsciiChem.parse("H_2 + O_2 -> H_2O")
diagnostics = AsciiChem::Linter.run(formula)
diagnostics.each { |d| puts d }

Or via CLI:

Terminal window
asciichem lint -i "H_2 + O_2 -> H_2O"
asciichem lint -i "..." -f json
CheckSeverityWhat it validates
BalanceCheckerrorStoichiometric atom conservation in reactions
ChargeBalanceCheckerrorCharge conservation in reactions (v0.7+)
BracketBalanceCheckerrorGroup bracket consistency
CrystalSanityCheckerrorCell lengths positive, angles in (0, 180], fractional coords in [0, 1)
ZMatrixReferenceCheckerrorReferences point to earlier rows; distances positive
SpectrumPeakCheckwarningPeak positions and intensities are numeric
ElementValidationCheckwarningElement symbols in the periodic table
IsotopeSanityCheckwarningIsotope mass ≥ atomic number
UnclosedRingCheckerrorRing closure digits have matching pairs
ValenceCheckerrorBond order + charge ≤ max valence
IdentifierFormatCheckerror@cas/@inchi/@inchikey/@smiles values parse offline (check digits, layer structure)
IdentifierConsistencyCheckerror/warningIdentifier values agree with the molecule they annotate (InChI formula layer, SMILES element set)
IdentityCrossCheckerror/warningDerives the structure’s InChI via the configured engine and compares against @inchi/@inchikey annotations; mismatch = error, absent engine = one guidance warning
diagnostic.severity # => :error, :warning, or :info
diagnostic.message # => "Reaction is not balanced: H: 2 vs 4"
diagnostic.node # => the Model::Node that triggered it
class MyCheck < AsciiChem::Linter::Base
register :my_check
def run(formula)
diagnostics = []
walk(formula) do |node|
# check each node...
end
diagnostics
end
end

Self-registers at file-load time via Linter::Base.register.

Play