Skip to content

Instantly share code, notes, and snippets.

@elias551
Created June 5, 2019 09:36
Show Gist options
  • Save elias551/2d58096890ba0dd8772f3b5a1668b9fd to your computer and use it in GitHub Desktop.
Save elias551/2d58096890ba0dd8772f3b5a1668b9fd to your computer and use it in GitHub Desktop.
masala parser calculation sample
import { C, F, N, Streams } from '@masala/parser'
/*
Implementing general solution :
E -> T E'
E' -> + TE' | eps
T -> F T'
T' -> * FT' | eps
F -> DAY | ( E )
E== expr
T == subExpr
E'== optPlusExpr
T' == optMultExpr
F == terminal
expr -> subExpr optPlusExpr'
optPlusExpr -> ( + then subExpr then F.lazy(optPlusExpr) ).opt()
subExpr -> terminal then optMultExpr
optMultExpr -> ( * then terminal then F.lazy(optMultExpr) ).opt()
F -> F.try( '(' then expr then ')' ).or(N.litteral)
*/
const MULT = Symbol('MULT')
const PLUS = Symbol('PLUS')
function text() {
return F.not(anyOperation().or(C.charIn('()')))
.rep()
.map(v => parseInt(v.join('').trim(), 10))
}
function blank() {
return C.char(' ')
.rep()
.returns(' ')
}
function anyOperation() {
return C.string('*')
.returns(MULT)
.or(C.string('+').returns(PLUS))
}
function andOperation() {
return C.string('*').returns(MULT)
}
function plusOperation() {
return C.string('+').returns(PLUS)
}
function parenthesis(par) {
return C.char(' ')
.optrep()
.drop()
.then(C.char(par))
}
function parenthesisExpr() {
return parenthesis('(')
.then(blank().opt())
.drop()
.then(F.lazy(expr))
.then(
parenthesis(')')
.then(blank().opt())
.drop()
)
}
function expr() {
return subExpr()
.then(optionalPlusExpr())
.map(v => {
const left = v.at(0) as any
const right = v.at(1) as any
return left + right.orElse(0)
})
}
function optionalPlusExpr() {
return plusExpr().opt()
}
function plusExpr() {
return plusOperation()
.drop()
.then(subExpr())
.then(F.lazy(optionalPlusExpr))
.map(v => {
const left = v.at(0) as any
const right = v.at(1) as any
return left + right.orElse(0)
})
}
function subExpr() {
return terminal()
.then(optionalMultExpr())
.map(v => {
const left = v.at(0) as any
const right = v.at(1) as any
return left * right.orElse(1)
})
}
function optionalMultExpr() {
return multExpr().opt()
}
function multExpr() {
return andOperation()
.drop()
.then(terminal())
.then(F.lazy(optionalMultExpr))
.map(v => {
const left = v.at(0) as any
const right = v.at(1) as any
return left * right.orElse(1)
})
}
function terminal() {
return F.try(parenthesisExpr()).or(text())
}
function combinator() {
return expr().then(F.eos().drop())
}
const input = '2 + 3 * ( ( 4 + 10) + ( 4) ) + 1 * -3'
const stream = Streams.ofString(input)
const parsing = combinator().parse(stream)
console.log(input + '=' + JSON.stringify(parsing.value, null, 2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment