Chemical calculator: Difference between revisions

(JavaScript added)
Line 2,190:
C₂₇H₄₆O: 387
Uue: 315
</pre>
 
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
jq is well-suited to "Parsing Expression Grammars" (PEGs) so
this entry illustrates how to implement the chemical calculator using a PEG approach.
 
In the remainder of this entry we focus on the highlights. The complete program is on the
subpage at [[Chemical calculator/jq]].
 
To understand the PEG grammar presented below, here is a table showing
the correspondence between the main PEG operators (on the left) and jq constructs (on the right),
the first two of which (`|` and `//`)
are part of the jq language, and the others of which are defined as jq functions
on the subpage.
 
<pre>
Sequence: e1 e2 e1 | e2
Ordered choice: e1 / e2 e1 // e2
Zero-or-more: e* star(E)
One-or-more: e+ plus(E)
Optional: e? optional(E)
And-predicate: &e amp(E)
Not-predicate: !e neg(E)
</pre>
 
'''The PEG grammar'''
<lang jq>def Element:
parse("(?<e>^[A-Z][a-z]*)"); # greedy
 
def Number: parseNumber("^[0-9]+"); # greedy
 
def EN: Element | optional(Number);
 
def Parenthesized:
consume("[(]")
| box( (plus(EN) | optional(Parenthesized)) // (Parenthesized | plus(EN)) )
| consume("[)]")
| Number;
 
def Formula:
(plus(EN) | Parenthesized | Formula)
// (plus(EN) | optional(Parenthesized))
// (Parenthesized | Formula) ;</lang>
'''Evaluation of the parsed expression'''
 
This is accomplished using the `eval` function defined on the subpage.
 
'''The task expressed in terms of assertions'''
<lang># A "debug" statement has been retained so that the parsed chemical formula can be seen.
def molar_mass(formula):
{remainder: formula} | Formula | .result | debug | eval;
 
def assert(a; b):
if (a - b) > 1e-3 then "\(a) != \(b)" else empty end;
 
def task:
assert( 1.008; molar_mass("H")), # hydrogen
assert( 2.016; molar_mass("H2")), # hydrogen gas
assert( 18.015; molar_mass("H2O")), # water
assert( 34.014; molar_mass("H2O2")), # hydrogen peroxide
assert( 34.014; molar_mass("(HO)2")), # hydrogen peroxide
assert( 142.036; molar_mass("Na2SO4")), # sodium sulfate
assert( 84.162; molar_mass("C6H12")), # cyclohexane
assert( 186.295; molar_mass("COOH(C(CH3)2)3CH3")), # butyric or butanoic acid
assert( 176.124; molar_mass("C6H4O2(OH)4")), # vitamin C ##
assert( 386.664; molar_mass("C27H46O")), # cholesterol
assert( 315 ; molar_mass("Uue")) # ununennium
;
</lang>
As mentioned above, a "debug" statement has been retained so that the parsed chemical formula can be seen.
{{out}}
<pre>
["DEBUG:",["H"]]
["DEBUG:",["H",2]]
["DEBUG:",["H",2,"O"]]
["DEBUG:",["H",2,"O",2]]
["DEBUG:",["Na",2,"S","O",4]]
["DEBUG:",["C",6,"H",12]]
["DEBUG:",["C","O","O","H",["C",["C","H",3],2],3,"C","H",3]]
["DEBUG:",["C",6,"H",4,"O",2,["O","H"],4]]
["DEBUG:",["C",27,"H",46,"O"]]
["DEBUG:",["Uue"]]
</pre>
 
2,465

edits