diff --git a/src/execute/lex-pipe.ts b/src/execute/lex-pipe.ts index 897a0b6d..cdb8f71d 100644 --- a/src/execute/lex-pipe.ts +++ b/src/execute/lex-pipe.ts @@ -52,6 +52,13 @@ export class LexPipe extends Frame implements IFinish, IPerformer { break } case 'pop': { + if (this.level === 0) { + console.error('LexPipe.perform.pop.failed: already at top level') + break + } + if (!parser.canPop(value)) { + break + } const next_parser = parser.pop(value) this.set(Frame.kOUT, next_parser) this.level -= 1 diff --git a/src/execute/parse-pipe.ts b/src/execute/parse-pipe.ts index 825df53d..efe9f76b 100644 --- a/src/execute/parse-pipe.ts +++ b/src/execute/parse-pipe.ts @@ -35,14 +35,18 @@ export class ParsePipe extends FrameArray implements IFinish { public pop (Factory: any): Frame { const parent = this.get(ParsePipe.kOUT) as ParsePipe - if (parent.Factory !== Factory) { - const msg = [' open:', parent.Factory, ' close:', Factory] - console.error('pop.mismatched-brackets' + msg.join('')) - } this.finish(Frame.nil) return parent } + public canPop (Factory: any): boolean { + const match = (this.Factory.name === Factory.name) + if (!match) { + console.error(`ParsePipe.canPop.failed: ${Factory.name} cannot pop ${this.Factory.name}`) + } + return match + } + public finish (terminal: any): Frame { this.next() const out = this.get(Frame.kOUT) diff --git a/test/execute/evaluate-spec.ts b/test/execute/evaluate-spec.ts index a78fb992..139d264b 100644 --- a/test/execute/evaluate-spec.ts +++ b/test/execute/evaluate-spec.ts @@ -85,5 +85,35 @@ describe('evaluate', () => { const output = result.at(0) expect(output).to.be.instanceof(frame.FrameLazy) }) + + it('returns FrameNote for empty ()', () => { + const result = evaluate('()') + const output = result.at(0) + expect(output).to.be.instanceof(frame.FrameNote) + }) + + it('returns FrameArray for empty [] with spaces', () => { + const result = evaluate(' [ ] ') + const output = result.at(0) + expect(output).to.be.instanceof(frame.FrameArray) + }) + + it('returns FrameArray for empty [] with comments', () => { + const result = evaluate('[#comment#]') + const output = result.at(0) + expect(output).to.be.instanceof(frame.FrameArray) + }) + + it('returns FrameNote for mis-matched brackets', () => { + const result = evaluate('[}') + const output = result.at(0) + expect(output).to.be.instanceof(frame.FrameNote) + }) + + it('returns FrameNote for un-opened close bracket', () => { + const result = evaluate('}') + const output = result.at(0) + expect(output).to.be.instanceof(frame.FrameNote) + }) }) })