diff --git a/package.json b/package.json index cb6d3247..a473e447 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,10 @@ "start:web": "yarn workspace @dbgate/web start", "start:sqltree": "yarn workspace @dbgate/sqltree start", "start:datalib": "yarn workspace @dbgate/datalib start", + "start:filterparser": "yarn workspace @dbgate/filterparser start", "start": "concurrently --kill-others-on-fail \"yarn start:api\" \"yarn start:web\"", - "lib": "concurrently --kill-others-on-fail \"yarn start:sqltree\" \"yarn start:datalib\"", + "lib": "concurrently --kill-others-on-fail \"yarn start:sqltree\" \"yarn start:datalib\" \"yarn start:filterparser\"", "ts:api": "yarn workspace @dbgate/api ts", "ts:web": "yarn workspace @dbgate/web ts", diff --git a/packages/filterparser/.gitignore b/packages/filterparser/.gitignore new file mode 100644 index 00000000..7951405f --- /dev/null +++ b/packages/filterparser/.gitignore @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/packages/filterparser/package.json b/packages/filterparser/package.json new file mode 100644 index 00000000..cdaab660 --- /dev/null +++ b/packages/filterparser/package.json @@ -0,0 +1,25 @@ +{ + "version": "0.1.0", + "name": "@dbgate/filterparser", + "main": "lib/index.js", + "typings": "lib/index.d.ts", + "scripts": { + "prepare": "yarn build", + "build": "tsc", + "start": "tsc --watch", + "test": "jest" + }, + "files": [ + "lib" + ], + "devDependencies": { + "@dbgate/types": "^0.1.0", + "@types/node": "^13.7.0", + "typescript": "^3.7.5" + }, + "dependencies": { + "@types/parsimmon": "^1.10.1", + "lodash": "^4.17.15", + "parsimmon": "^1.13.0" + } +} diff --git a/packages/filterparser/src/parseFilter.ts b/packages/filterparser/src/parseFilter.ts new file mode 100644 index 00000000..5e834a35 --- /dev/null +++ b/packages/filterparser/src/parseFilter.ts @@ -0,0 +1,44 @@ +import P from 'parsimmon'; +import { FilterType } from './types'; + +const whitespace = P.regexp(/\s*/m); + +function token(parser) { + return parser.skip(whitespace); +} + +function interpretEscapes(str) { + let escapes = { + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t', + }; + return str.replace(/\\(u[0-9a-fA-F]{4}|[^u])/, (_, escape) => { + let type = escape.charAt(0); + let hex = escape.slice(1); + if (type === 'u') { + return String.fromCharCode(parseInt(hex, 16)); + } + if (escapes.hasOwnProperty(type)) { + return escapes[type]; + } + return type; + }); +} + +const parser = P.createLanguage({ + expr: r => P.alt(r.string), + + string: () => + token(P.regexp(/"((?:\\.|.)*?)"/, 1)) + .map(interpretEscapes) + .desc('string'), +}); + +export function parseFilter(value: string, filterType: FilterType) { + const ast = parser.expr.tryParse(value); + console.log(ast); + return ast; +} diff --git a/packages/filterparser/src/parserFilter.test.ts b/packages/filterparser/src/parserFilter.test.ts new file mode 100644 index 00000000..3ff535b7 --- /dev/null +++ b/packages/filterparser/src/parserFilter.test.ts @@ -0,0 +1,3 @@ +import parserFilter, { parseFilter } from './parseFilter'; + +test('parse string', parseFilter('"123"', 'string')); diff --git a/packages/filterparser/src/types.ts b/packages/filterparser/src/types.ts new file mode 100644 index 00000000..1bc1e73d --- /dev/null +++ b/packages/filterparser/src/types.ts @@ -0,0 +1,3 @@ +// import types from '@dbgate/types'; + +export type FilterType = 'number' | 'string' | 'datetime' | 'logical'; diff --git a/packages/filterparser/tsconfig.json b/packages/filterparser/tsconfig.json new file mode 100644 index 00000000..b2671e70 --- /dev/null +++ b/packages/filterparser/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2015", + "module": "commonjs", + "declaration": true, + "skipLibCheck": true, + "outDir": "lib", + "preserveWatchOutput": true, + "esModuleInterop": true + }, + "include": [ + "src/**/*" + ] +} diff --git a/yarn.lock b/yarn.lock index 0b7da6bb..b58bd474 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1489,6 +1489,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/parsimmon@^1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@types/parsimmon/-/parsimmon-1.10.1.tgz#d46015ad91128fce06a1a688ab39a2516507f740" + integrity sha512-MoF2IC9oGSgArJwlxdst4XsvWuoYfNUWtBw0kpnCi6K05kV+Ecl7siEeJ40tgCbI9uqEMGQL/NlPMRv6KVkY5Q== + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -8427,6 +8432,11 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +parsimmon@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.13.0.tgz#6e4ef3dbd45ed6ea6808be600ac4b9c8a44228cf" + integrity sha512-5UIrOCW+gjbILkjKPgTgmq8LKf8TT3Iy7kN2VD7OtQ81facKn8B4gG1X94jWqXYZsxG2KbJhrv/Yq/5H6BQn7A== + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"