-
Notifications
You must be signed in to change notification settings - Fork 0
/
polynomial.js
68 lines (63 loc) · 2.19 KB
/
polynomial.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const ohm = require('ohm-js');
const grammar = ohm.grammar(`Polynomial {
Poly
= Poly "+" term -- add
| Poly "-" term -- subtract
| "-" Poly -- negate
| term
term
= coefficient "x^" exponent -- coeff_var_exp
| coefficient "x" -- coeff_var
| coefficient -- coeff
| "x^" exponent -- var_exp
| "x" -- var
coefficient
= digit+ ("." digit+)?
exponent
= "-"? digit+
}`);
const semantics = grammar.createSemantics().addOperation('deriv', {
Poly_add(p, op, t) {return `${p.deriv()}+${t.deriv()}`;},
Poly_subtract(p, op, t) {return `${p.deriv()}-${t.deriv()}`;},
Poly_negate(_, p) {return `-${p.deriv()}`;},
term_coeff_var_exp(c, _, e) {return `${e.value * c.value}x^${e.value - 1}`;},
term_coeff_var(c, _) {return `${c.value}`;},
term_coeff(c) {return `0`;},
term_var_exp(_, e) {return `${e.value}x^${e.value - 1}`;},
term_var(_) {return `1`;},
}).addOperation('eval', {
Poly_add(p, op, t) {return x => p.eval()(x) + t.eval()(x);},
Poly_subtract(p, op, t) {return x => p.eval()(x) - t.eval()(x);},
Poly_negate(_, p) {return x => -p.eval()(x);},
term_coeff_var_exp(c, _, e) {return x => c.value * Math.pow(x, e.value);},
term_coeff_var(c, _) {return x => c.value * x;},
term_coeff(c) {return x => c.value;},
term_var_exp(_, e) {return x => Math.pow(x,e.value);},
term_var(_) {return x => x;},
}).addAttribute('value', {
coefficient(whole, dot, fraction) {return +this.sourceString;},
exponent(sign, magnitude) {return +this.sourceString;},
});
exports.derivative = poly => {
let match = grammar.match(poly);
if (!match.succeeded()) {
throw new Error(match.message);
}
return semantics(match).deriv().replace(/--/g, '+').replace(/\+-/g, '-');
}
exports.evaluate = (poly, x) => {
let match = grammar.match(poly);
if (!match.succeeded()) {
throw new Error(match.message);
}
return semantics(match).eval()(x);
}
if (!module.parent) {
let match = grammar.match(process.argv[2]);
if (match.succeeded()) {
console.log(semantics(match).deriv());
} else {
console.error(match.message);
process.exitCode = 1;
}
}