fix: expression and string literal parser, #186

This commit is contained in:
harttle
2020-02-08 03:15:55 +08:00
parent 46b69db87a
commit fc0cf6fe7b
8 changed files with 222 additions and 50 deletions
+43
View File
@@ -0,0 +1,43 @@
import { tokenize } from '../../../src/parser/expression-tokenizer'
import { expect } from 'chai'
describe('expression tokenizer', () => {
describe('spaces', () => {
it('should tokenize a + b', () => {
expect([...tokenize('a + b')]).to.deep.equal(['a', '+', 'b'])
})
it('should tokenize a==1', () => {
expect([...tokenize('a==1')]).to.deep.equal(['a', '==', '1'])
})
})
describe('range', () => {
it('should tokenize (1..3) contains 3', () => {
expect([...tokenize('(1..3)')]).to.deep.equal(['(1..3)'])
})
})
describe('bracket', () => {
it('should tokenize a[b] = c', () => {
expect([...tokenize('a[b] = c')]).to.deep.equal(['a[b]', '=', 'c'])
})
it('should tokenize c[a["b"]] < c', () => {
expect([...tokenize('c[a["b"]] < c')]).to.deep.equal(['c[a["b"]]', '<', 'c'])
})
it('should tokenize "][" == var', () => {
expect([...tokenize('"][" == var')]).to.deep.equal(['"]["', '==', 'var'])
})
})
describe('quotes', () => {
it('should tokenize " " == var', () => {
expect([...tokenize('" " == var')]).to.deep.equal(['" "', '==', 'var'])
})
it('should tokenize "\\\'" == var', () => {
expect([...tokenize('"\\\'" == var')]).to.deep.equal(['"\\\'"', '==', 'var'])
})
it('should tokenize "\\"" == var', () => {
expect([...tokenize('"\\"" == var')]).to.deep.equal(['"\\""', '==', 'var'])
})
})
})
+35 -2
View File
@@ -1,8 +1,8 @@
import { expect } from 'chai'
import { parseLiteral } from '../../../src/parser/literal'
import { parseLiteral, parseStringLiteral } from '../../../src/parser/literal'
import { NullDrop } from '../../../src/drop/null-drop'
describe('parseLiteral', function () {
describe('parseLiteral()', function () {
it('should eval boolean literal', async function () {
expect(parseLiteral('true')).to.equal(true)
expect(parseLiteral('TrUE')).to.equal(undefined)
@@ -25,3 +25,36 @@ describe('parseLiteral', function () {
expect(parseLiteral('null')).to.be.instanceOf(NullDrop)
})
})
describe('parseStringLiteral()', function () {
it('should parse octal escape', () => {
expect(parseStringLiteral(String.raw`"\1010"`)).to.equal('A0')
expect(parseStringLiteral(String.raw`"\12"`)).to.equal('\n')
expect(parseStringLiteral(String.raw`"\01"`)).to.equal('\u0001')
expect(parseStringLiteral(String.raw`"\0"`)).to.equal('\0')
})
it('should skip invalid octal escape', () => {
expect(parseStringLiteral(String.raw`"\9"`)).to.equal('9')
})
it('should parse \n, \t, \r', () => {
expect(parseStringLiteral(String.raw`"fo\no"`)).to.equal('fo\no')
expect(parseStringLiteral(String.raw`'fo\to'`)).to.equal('fo\to')
expect(parseStringLiteral(String.raw`'fo\ro'`)).to.equal('fo\ro')
})
it('should parse unicode(hex) escape', () => {
expect(parseStringLiteral('"\\u003C"')).to.equal('<')
expect(parseStringLiteral('"\\u003cZ"')).to.equal('<Z')
expect(parseStringLiteral('"\\u41"')).to.equal('A')
})
it('should skip invalid unicode(hex) escape', () => {
expect(parseStringLiteral('"\\u41Z"')).to.equal('AZ')
expect(parseStringLiteral('"\\uZ"')).to.equal('\0Z')
})
it('should parse quote escape', () => {
expect(parseStringLiteral(String.raw`"fo\'o"`)).to.equal("fo'o")
expect(parseStringLiteral(String.raw`'fo\"o'`)).to.equal('fo"o')
})
it('should parse slash escape', () => {
expect(parseStringLiteral(String.raw`'fo\\o'`)).to.equal('fo\\o')
})
})
+21 -1
View File
@@ -11,9 +11,14 @@ describe('Expression', function () {
one: 1,
two: 2,
empty: '',
quote: '"',
space: ' ',
x: 'XXX',
y: undefined,
z: null
z: null,
obj: {
']': 'right bracket'
}
})
})
@@ -26,6 +31,8 @@ describe('Expression', function () {
})
it('should eval simple expression', async function () {
expect(await toThenable(new Expression('1==2').value(ctx))).to.equal(false)
expect(await toThenable(new Expression('1<2').value(ctx))).to.equal(true)
expect(await toThenable(new Expression('1 < 2').value(ctx))).to.equal(true)
expect(await toThenable(new Expression('1 < 2').value(ctx))).to.equal(true)
expect(await toThenable(new Expression('2 <= 2').value(ctx))).to.equal(true)
@@ -40,6 +47,19 @@ describe('Expression', function () {
expect(await toThenable(new Expression('"<=" == "<="').value(ctx))).to.equal(true)
})
it('should allow space in quoted value', async function () {
expect(await toThenable(new Expression('" " == space').value(ctx))).to.equal(true)
})
describe('escape', () => {
it('should escape quote', async function () {
expect(await toThenable(new Expression('"\\"" == quote').value(ctx))).to.equal(true)
})
it('should escape square bracket', async function () {
expect(await toThenable(new Expression('obj["]"] == "right bracket"').value(ctx))).to.equal(true)
})
})
describe('complex expression', function () {
it('should support value or value', async function () {
expect(await toThenable(new Expression('false or true').value(ctx))).to.equal(true)