fix shunting yard
This commit is contained in:
parent
d9ebc1e875
commit
3a776ca1e1
3 changed files with 52 additions and 16 deletions
|
@ -1,4 +1,4 @@
|
|||
import { assocPath, curry, identity, is, last, mergeRightDeep, path } from '../fn.js'
|
||||
import { curry, is, last, mergeRightDeep, path } from '../fn.js'
|
||||
import { Stream } from '../stream.js'
|
||||
|
||||
class Value {
|
||||
|
@ -97,11 +97,11 @@ export class Function {
|
|||
|
||||
#pop(stack) {
|
||||
const result = []
|
||||
const len = stack.length - 1
|
||||
const n = Math.min(this.length, len)
|
||||
let n = Math.min(this.length, stack.length)
|
||||
|
||||
for(let i = len; i >= len - n; i--) {
|
||||
while(n > 0) {
|
||||
result.push(stack.pop())
|
||||
n--
|
||||
}
|
||||
|
||||
result.reverse()
|
||||
|
@ -122,14 +122,14 @@ const Associativity = Object.freeze({
|
|||
export class Operator extends Function {
|
||||
constructor(name, fn, priority, associativity = Associativity.Left, length = fn.length) {
|
||||
super(name, fn, length)
|
||||
this.priority = priority
|
||||
this.precedence = priority
|
||||
this.associativity = associativity
|
||||
}
|
||||
|
||||
compare(other) {
|
||||
if (other.priority > this.priority) {
|
||||
if (other.precedence < this.precedence) {
|
||||
return 1
|
||||
} else if (other.priority === this.priority) {
|
||||
} else if (other.precedence === this.precedence) {
|
||||
if (this.associativity === Associativity.Left) {
|
||||
return 1
|
||||
} else {
|
||||
|
@ -185,9 +185,10 @@ export class Filter {
|
|||
const next = stream.next()
|
||||
if (is(Function, next)) {
|
||||
if (is(Operator, next)) {
|
||||
const ops = this.#takeUntil(op => leftParen(op) && next.compare(op) <= 0, operators)
|
||||
const ops = this.#takeWhile(op => !leftParen(op) && next.compare(op) > 0, operators)
|
||||
output.push.apply(output, ops)
|
||||
}
|
||||
|
||||
operators.push(next)
|
||||
} else if (comma(next)) {
|
||||
output.push.apply(output, this.#takeUntil(leftParen, operators))
|
||||
|
@ -196,9 +197,11 @@ export class Filter {
|
|||
} else if (rightParen(next)) {
|
||||
const ops = this.#takeUntil(leftParen, operators)
|
||||
output.push.apply(output, ops)
|
||||
|
||||
if (!leftParen(operators.pop())) {
|
||||
throw new SyntaxError('mismatched parenthesis')
|
||||
}
|
||||
|
||||
if (is(Function, last(operators))) {
|
||||
output.push(operators.pop())
|
||||
}
|
||||
|
@ -226,13 +229,13 @@ export class Filter {
|
|||
const next = stream.next()
|
||||
if (is(Operator, next)) {
|
||||
const result = next.apply(stack)
|
||||
stack.unshift(result)
|
||||
stack.push(result)
|
||||
} else {
|
||||
stack.push(next)
|
||||
}
|
||||
}
|
||||
|
||||
return stack.every(identity)
|
||||
return stack[0]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ export class Iterator {
|
|||
let accumulator = []
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
if(this.done()) {
|
||||
if (this.done()) {
|
||||
break
|
||||
}
|
||||
accumulator.push(this.next())
|
||||
|
@ -49,10 +49,37 @@ export class Iterator {
|
|||
return accumulator
|
||||
}
|
||||
|
||||
takeWhile(fn) {
|
||||
const accumulator = []
|
||||
|
||||
while (!this.done() || fn(this.peek())) {
|
||||
accumulator.push(this.next())
|
||||
}
|
||||
|
||||
return accumulator
|
||||
}
|
||||
|
||||
takeUntil(fn) {
|
||||
return this.takeWhile(x => !fn(x))
|
||||
}
|
||||
|
||||
drop(n) {
|
||||
this.take(n)
|
||||
return this
|
||||
}
|
||||
|
||||
dropWhile(fn) {
|
||||
while(!this.done() || fn(this.peek())) {
|
||||
this.next()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
dropUntil(fn) {
|
||||
this.dropWhile(x => !fn(x))
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayIterator extends Iterator {
|
||||
|
|
|
@ -121,12 +121,18 @@ describe('query', () => {
|
|||
)
|
||||
|
||||
assert.deepEqual(
|
||||
query('MATCH (e, h:Health) WHERE h.max = 50 OR h.current < 50 RETURN e, h.max AS maxHealth', engine).unwrap(),
|
||||
query('MATCH (e, h:Health) WHERE h.max = 50 OR h.current > 45 RETURN e, h.max AS maxHealth', engine).unwrap(),
|
||||
[
|
||||
{ e: 12, maxHealth: 50 },
|
||||
{ e: 13, maxHealth: 50 }
|
||||
]
|
||||
)
|
||||
assert.deepEqual(
|
||||
query('MATCH (e, :Player, h:Health) WHERE (h.max = 50 OR h.current > 45) AND e = 12 RETURN e, h.max AS maxHealth', engine).unwrap(),
|
||||
[
|
||||
{ e: 12, maxHealth: 50 }
|
||||
]
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue