lexer impl WIP + test

This commit is contained in:
zadam 2020-05-17 19:43:37 +02:00
parent 32eaafd024
commit e77e0ce675
9 changed files with 384 additions and 211 deletions

413
package-lock.json generated
View File

@ -17,9 +17,9 @@
"dev": true
},
"@babel/runtime": {
"version": "7.9.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
"integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
"version": "7.9.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz",
"integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
@ -198,26 +198,24 @@
}
},
"@jimp/bmp": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.10.3.tgz",
"integrity": "sha512-keMOc5woiDmONXsB/6aXLR4Z5Q+v8lFq3EY2rcj2FmstbDMhRuGbmcBxlEgOqfRjwvtf/wOtJ3Of37oAWtVfLg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.12.0.tgz",
"integrity": "sha512-PjgGVaSQvPrepsD52aTQe6B8A1G/OOYIcpXt6K59AUHQE3s6oNo9lYfyUv96gInBBIMze9s8AgLhMLjU8ijw4Q==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"bmp-js": "^0.1.0",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0",
"bmp-js": "^0.1.0"
}
},
"@jimp/core": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.10.3.tgz",
"integrity": "sha512-Gd5IpL3U2bFIO57Fh/OA3HCpWm4uW/pU01E75rI03BXfTdz3T+J7TwvyG1XaqsQ7/DSlS99GXtLQPlfFIe28UA==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.12.0.tgz",
"integrity": "sha512-xLF8gvRyJSCu08PI01b/MFijxoBoPusJFbSOOzMnP286qVDouxdXQy6CJB3mMosnlZRgp12I+ZgUvMsdJsL8ig==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"@jimp/utils": "^0.12.0",
"any-base": "^1.1.0",
"buffer": "^5.2.0",
"core-js": "^3.4.1",
"exif-parser": "^0.1.12",
"file-type": "^9.0.0",
"load-bmfont": "^1.3.1",
@ -235,323 +233,294 @@
}
},
"@jimp/custom": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.10.3.tgz",
"integrity": "sha512-nZmSI+jwTi5IRyNLbKSXQovoeqsw+D0Jn0SxW08wYQvdkiWA8bTlDQFgQ7HVwCAKBm8oKkDB/ZEo9qvHJ+1gAQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.12.0.tgz",
"integrity": "sha512-Rf3p50Jmvy9Aeovs0kyIpd0qbt2peLqDRq6f93AlDkUpB6OZ/rQwgJO8yysNMgI877a3xQz0Tda5j5Lv8AjWgA==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/core": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/core": "^0.12.0"
}
},
"@jimp/gif": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.10.3.tgz",
"integrity": "sha512-vjlRodSfz1CrUvvrnUuD/DsLK1GHB/yDZXHthVdZu23zYJIW7/WrIiD1IgQ5wOMV7NocfrvPn2iqUfBP81/WWA==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.12.0.tgz",
"integrity": "sha512-CMapyrH5LGXbl2jHgQA923wHUNbC0LajqMmMHfyFZE9GZFzXULqbTZdRemHXTXn++iruPSR37oVUYi67WG9qmQ==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/utils": "^0.12.0",
"omggif": "^1.0.9"
}
},
"@jimp/jpeg": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.10.3.tgz",
"integrity": "sha512-AAANwgUZOt6f6P7LZxY9lyJ9xclqutYJlsxt3JbriXUGJgrrFAIkcKcqv1nObgmQASSAQKYaMV9KdHjMlWFKlQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.12.0.tgz",
"integrity": "sha512-jAC9gWPCBJ0ysTZDqDUOVUty3/tk2qStw3N5Vk9W3XZNSTNlLp5xWsiATlkAoSrwoBmdgjf6OfZwqmkFDFVMKw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/utils": "^0.12.0",
"jpeg-js": "^0.3.4"
}
},
"@jimp/plugin-blit": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.10.3.tgz",
"integrity": "sha512-5zlKlCfx4JWw9qUVC7GI4DzXyxDWyFvgZLaoGFoT00mlXlN75SarlDwc9iZ/2e2kp4bJWxz3cGgG4G/WXrbg3Q==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.12.0.tgz",
"integrity": "sha512-csSxB/ZOljGLtvRne+nF1EGpcHZ/6mdGc+trcihClTTLAS5FzX+tySpQj9sHrIzzHtEcILYPMOKaf6KC4LOrfw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-blur": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.10.3.tgz",
"integrity": "sha512-cTOK3rjh1Yjh23jSfA6EHCHjsPJDEGLC8K2y9gM7dnTUK1y9NNmkFS23uHpyjgsWFIoH9oRh2SpEs3INjCpZhQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.12.0.tgz",
"integrity": "sha512-HCL570HvZxhT7Yn/Qqow00sRK0J/E4j1Clwp78vMnQWQ38PONi/Ipyjqp0RLdvCj3tJ3mzrKDqlnN2bbLcKsjQ==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-circle": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.10.3.tgz",
"integrity": "sha512-51GAPIVelqAcfuUpaM5JWJ0iWl4vEjNXB7p4P7SX5udugK5bxXUjO6KA2qgWmdpHuCKtoNgkzWU9fNSuYp7tCA==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.12.0.tgz",
"integrity": "sha512-d+cRlyrM4ylXKk6TuFZcoFz8xsXqLHGfZcX+BDFe9HPz+TTW7AoL5eq8I0uLpTHRD1dLdBPScMejkn3ppLKnjg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-color": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.10.3.tgz",
"integrity": "sha512-RgeHUElmlTH7vpI4WyQrz6u59spiKfVQbsG/XUzfWGamFSixa24ZDwX/yV/Ts+eNaz7pZeIuv533qmKPvw2ujg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.12.0.tgz",
"integrity": "sha512-RmPSwryrmLLtsNluQ9hT73EovM+KcthacDmF7VN/xnJMD/r+vXfgUcDLZDx8yQsd5kdezhtPh7wKihH2+voOwg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/utils": "^0.12.0",
"tinycolor2": "^1.4.1"
}
},
"@jimp/plugin-contain": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.10.3.tgz",
"integrity": "sha512-bYJKW9dqzcB0Ihc6u7jSyKa3juStzbLs2LFr6fu8TzA2WkMS/R8h+ddkiO36+F9ILTWHP0CIA3HFe5OdOGcigw==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.12.0.tgz",
"integrity": "sha512-mA1l2GbtmY2uLdCiwzdSJa9tZSyL5uvQwT3UrKDWaPiyhT4+VrCgQVD4CBbOFztI8ToxPcGM9GG4oRuRR2cKDQ==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-cover": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.10.3.tgz",
"integrity": "sha512-pOxu0cM0BRPzdV468n4dMocJXoMbTnARDY/EpC3ZW15SpMuc/dr1KhWQHgoQX5kVW1Wt8zgqREAJJCQ5KuPKDA==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.12.0.tgz",
"integrity": "sha512-rTrGxCBr1dn6DOVF+g8IFUCXHpfOaZCC4kvOyx/GIE3861GqKyOWzjLRcWTVBfgyiuOx+S6kBwpadmnsFO8tHg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-crop": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.10.3.tgz",
"integrity": "sha512-nB7HgOjjl9PgdHr076xZ3Sr6qHYzeBYBs9qvs3tfEEUeYMNnvzgCCGtUl6eMakazZFCMk3mhKmcB9zQuHFOvkg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.12.0.tgz",
"integrity": "sha512-sEz1T7waD5c+nB0aJERipc8/LSaRo4IxPzemOuzWaXxvwdUVRPtM7Rk7XOZmJyc2nW8qPNet+2JkaSjg848xgQ==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-displace": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.10.3.tgz",
"integrity": "sha512-8t3fVKCH5IVqI4lewe4lFFjpxxr69SQCz5/tlpDLQZsrNScNJivHdQ09zljTrVTCSgeCqQJIKgH2Q7Sk/pAZ0w==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.12.0.tgz",
"integrity": "sha512-VWlTF6TEDdGoN56tnOfsHVNNtsWBHCBmT77G+2k2agbXWAPD5A++bye0y4XP/icAS//sAd7UFzvNQlnT7sIAdg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-dither": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.10.3.tgz",
"integrity": "sha512-JCX/oNSnEg1kGQ8ffZ66bEgQOLCY3Rn+lrd6v1jjLy/mn9YVZTMsxLtGCXpiCDC2wG/KTmi4862ysmP9do9dAQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.12.0.tgz",
"integrity": "sha512-EzhHugll52ngdV1RBh1wmRUjf1jgo2GfU+Zh/a05uLxKGZEDWqGcsfFlI4lZnJbiKUhHCTNwZRCkV2w9gNJ6uw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-fisheye": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.10.3.tgz",
"integrity": "sha512-RRZb1wqe+xdocGcFtj2xHU7sF7xmEZmIa6BmrfSchjyA2b32TGPWKnP3qyj7p6LWEsXn+19hRYbjfyzyebPElQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.12.0.tgz",
"integrity": "sha512-Rz/gboWtY6sow6FC4tg9kG/fNBLopjGRoMmzHVcoQK1XXI2O/tH6nrliHHv3s3AvBBrQ5qPyO5VyCb1vm9xOmA==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-flip": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.10.3.tgz",
"integrity": "sha512-0epbi8XEzp0wmSjoW9IB0iMu0yNF17aZOxLdURCN3Zr+8nWPs5VNIMqSVa1Y62GSyiMDpVpKF/ITiXre+EqrPg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.12.0.tgz",
"integrity": "sha512-NFeIHWU95rSmIUnUdHVAYU4dYE3X10qY2peTgbMJ+q1J2qsrUO7w6Gepfd26tA9lh41zwDD5UzuAorpHQ3z27g==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-gaussian": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.10.3.tgz",
"integrity": "sha512-25eHlFbHUDnMMGpgRBBeQ2AMI4wsqCg46sue0KklI+c2BaZ+dGXmJA5uT8RTOrt64/K9Wz5E+2n7eBnny4dfpQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.12.0.tgz",
"integrity": "sha512-LXus5pMzUaIYGTCoWDxRiMb5AW0gJMqet3U6+mQIP7OtSnBL2Vimz9WBbzZuEfKRMCc1l6oDwD/o/fH5ehv+TQ==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-invert": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.10.3.tgz",
"integrity": "sha512-effYSApWY/FbtlzqsKXlTLkgloKUiHBKjkQnqh5RL4oQxh/33j6aX+HFdDyQKtsXb8CMd4xd7wyiD2YYabTa0g==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.12.0.tgz",
"integrity": "sha512-fkOBCFg9P3Nkc0aFgWt5WgRP41KOs9m8OOnIi4jLnvCamv/Fv8GJLMeDS3gIXuzb/XkS0W/WpMQJmvI1+Zj2xg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-mask": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.10.3.tgz",
"integrity": "sha512-twrg8q8TIhM9Z6Jcu9/5f+OCAPaECb0eKrrbbIajJqJ3bCUlj5zbfgIhiQIzjPJ6KjpnFPSqHQfHkU1Vvk/nVw==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.12.0.tgz",
"integrity": "sha512-BWe0n6EB5/b5H062Vybyd2rTkC7yV/DNtNgJiVseZiqJCwmOjZDq+Gx+gKmB3959Th9ipwdEt3nzwBwmyDBVwA==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-normalize": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.10.3.tgz",
"integrity": "sha512-xkb5eZI/mMlbwKkDN79+1/t/+DBo8bBXZUMsT4gkFgMRKNRZ6NQPxlv1d3QpRzlocsl6UMxrHnhgnXdLAcgrXw==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.12.0.tgz",
"integrity": "sha512-w66beKgxBI1Psv7BmKDxCFJOqAxzn4whVcHgsQ31627HFTelDAf9kSTUOdcIPEwWfWg0tzkKmnHGYQhfJUHYRw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-print": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.10.3.tgz",
"integrity": "sha512-wjRiI6yjXsAgMe6kVjizP+RgleUCLkH256dskjoNvJzmzbEfO7xQw9g6M02VET+emnbY0CO83IkrGm2q43VRyg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.12.0.tgz",
"integrity": "sha512-DdPAmPlTc0rNXRD7efLnCUD2VhYe9kx6h+2mCobGA3AHakrAdJ8qndkWF6UsYxlyrLXxVTftfWKhHOTGOGyA7Q==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/utils": "^0.12.0",
"load-bmfont": "^1.4.0"
}
},
"@jimp/plugin-resize": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.10.3.tgz",
"integrity": "sha512-rf8YmEB1d7Sg+g4LpqF0Mp+dfXfb6JFJkwlAIWPUOR7lGsPWALavEwTW91c0etEdnp0+JB9AFpy6zqq7Lwkq6w==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.12.0.tgz",
"integrity": "sha512-5qqrYmMeSyfNvFb+hdL1XDdGC2Db+/1KwWH9Zw3IxaAB4pXVPmZYMfBi9cJXd1mVHafl+FQWAEy5Ii3hXA32aw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-rotate": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.10.3.tgz",
"integrity": "sha512-YXLlRjm18fkW9MOHUaVAxWjvgZM851ofOipytz5FyKp4KZWDLk+dZK1JNmVmK7MyVmAzZ5jsgSLhIgj+GgN0Eg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.12.0.tgz",
"integrity": "sha512-tOgn86RoFyDm+BJOfdhPXNjaUiaotKcvMzfdR/o4kL/55y+x7xfVj7v7CJbvudnG29bDwEM+3r8HwfaQsezosg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-scale": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.10.3.tgz",
"integrity": "sha512-5DXD7x7WVcX1gUgnlFXQa8F+Q3ThRYwJm+aesgrYvDOY+xzRoRSdQvhmdd4JEEue3lyX44DvBSgCIHPtGcEPaw==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.12.0.tgz",
"integrity": "sha512-FS8MWgUcCZ1nwFX4YupTK59nuTqK8seo2CXJeHXgGjl8UU6c/EPBD9SrAuqSNbngcDY9fZ65i6srUyqrQ8kk7w==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-shadow": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.10.3.tgz",
"integrity": "sha512-/nkFXpt2zVcdP4ETdkAUL0fSzyrC5ZFxdcphbYBodqD7fXNqChS/Un1eD4xCXWEpW8cnG9dixZgQgStjywH0Mg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.12.0.tgz",
"integrity": "sha512-FzzTVccC6BkL9Y0rFxI5Di4JEZvCxKq7AyyK6qI7OwBrwxoAmtUodkxGDZTUvYfpmtMZeLWG9TUVrJ/sBQ+NWA==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugin-threshold": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.10.3.tgz",
"integrity": "sha512-Dzh0Yq2wXP2SOnxcbbiyA4LJ2luwrdf1MghNIt9H+NX7B+IWw/N8qA2GuSm9n4BPGSLluuhdAWJqHcTiREriVA==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.12.0.tgz",
"integrity": "sha512-Sqf2MFDQY/kz0sAPtfjjG4BUcrF58lT09h2EJ75Rdc3hiAWrB7XizLvnI1J8rooHci8Ablbkb/E6xu+52KOGuw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1"
"@jimp/utils": "^0.12.0"
}
},
"@jimp/plugins": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.10.3.tgz",
"integrity": "sha512-jTT3/7hOScf0EIKiAXmxwayHhryhc1wWuIe3FrchjDjr9wgIGNN2a7XwCgPl3fML17DXK1x8EzDneCdh261bkw==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.12.0.tgz",
"integrity": "sha512-P/1vKex4P697ayzVysMSjckcHE2Ii61tyNkq9t1RSZuERgyE616llVKMcil0aVYTnoqapjOwEW36c/fWY8Zj6g==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/plugin-blit": "^0.10.3",
"@jimp/plugin-blur": "^0.10.3",
"@jimp/plugin-circle": "^0.10.3",
"@jimp/plugin-color": "^0.10.3",
"@jimp/plugin-contain": "^0.10.3",
"@jimp/plugin-cover": "^0.10.3",
"@jimp/plugin-crop": "^0.10.3",
"@jimp/plugin-displace": "^0.10.3",
"@jimp/plugin-dither": "^0.10.3",
"@jimp/plugin-fisheye": "^0.10.3",
"@jimp/plugin-flip": "^0.10.3",
"@jimp/plugin-gaussian": "^0.10.3",
"@jimp/plugin-invert": "^0.10.3",
"@jimp/plugin-mask": "^0.10.3",
"@jimp/plugin-normalize": "^0.10.3",
"@jimp/plugin-print": "^0.10.3",
"@jimp/plugin-resize": "^0.10.3",
"@jimp/plugin-rotate": "^0.10.3",
"@jimp/plugin-scale": "^0.10.3",
"@jimp/plugin-shadow": "^0.10.3",
"@jimp/plugin-threshold": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/plugin-blit": "^0.12.0",
"@jimp/plugin-blur": "^0.12.0",
"@jimp/plugin-circle": "^0.12.0",
"@jimp/plugin-color": "^0.12.0",
"@jimp/plugin-contain": "^0.12.0",
"@jimp/plugin-cover": "^0.12.0",
"@jimp/plugin-crop": "^0.12.0",
"@jimp/plugin-displace": "^0.12.0",
"@jimp/plugin-dither": "^0.12.0",
"@jimp/plugin-fisheye": "^0.12.0",
"@jimp/plugin-flip": "^0.12.0",
"@jimp/plugin-gaussian": "^0.12.0",
"@jimp/plugin-invert": "^0.12.0",
"@jimp/plugin-mask": "^0.12.0",
"@jimp/plugin-normalize": "^0.12.0",
"@jimp/plugin-print": "^0.12.0",
"@jimp/plugin-resize": "^0.12.0",
"@jimp/plugin-rotate": "^0.12.0",
"@jimp/plugin-scale": "^0.12.0",
"@jimp/plugin-shadow": "^0.12.0",
"@jimp/plugin-threshold": "^0.12.0",
"timm": "^1.6.1"
}
},
"@jimp/png": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.10.3.tgz",
"integrity": "sha512-YKqk/dkl+nGZxSYIDQrqhmaP8tC3IK8H7dFPnnzFVvbhDnyYunqBZZO3SaZUKTichClRw8k/CjBhbc+hifSGWg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.12.0.tgz",
"integrity": "sha512-5MgVBRhjkivIHy7cJ6QnU4CygndSde0ZMcaVkfBIyh6gd8pCcIG/XbY2TcR9lSkflgw3tUVzLrFR1xWUYr2trg==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/utils": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/utils": "^0.12.0",
"pngjs": "^3.3.3"
}
},
"@jimp/tiff": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.10.3.tgz",
"integrity": "sha512-7EsJzZ5Y/EtinkBGuwX3Bi4S+zgbKouxjt9c82VJTRJOQgLWsE/RHqcyRCOQBhHAZ9QexYmDz34medfLKdoX0g==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.12.0.tgz",
"integrity": "sha512-h7HBCSjTA4YlnWx66qxQh9YxuzxMoBSGkTiUDEhao2BIhYa2pRmRwtMfqp1EdeRYcXkswWpn4qZAr7zY1TlIGw==",
"requires": {
"@babel/runtime": "^7.7.2",
"core-js": "^3.4.1",
"utif": "^2.0.1"
}
},
"@jimp/types": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.10.3.tgz",
"integrity": "sha512-XGmBakiHZqseSWr/puGN+CHzx0IKBSpsKlmEmsNV96HKDiP6eu8NSnwdGCEq2mmIHe0JNcg1hqg59hpwtQ7Tiw==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.12.0.tgz",
"integrity": "sha512-6avU1n9lY4vpAHjKSQqrLbk6L5PCNFORre+T1Rcyvv/CGQKxVIAuRj1w+RzXClob8MEmvI17OI3R2w5RCbYpQw==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/bmp": "^0.10.3",
"@jimp/gif": "^0.10.3",
"@jimp/jpeg": "^0.10.3",
"@jimp/png": "^0.10.3",
"@jimp/tiff": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/bmp": "^0.12.0",
"@jimp/gif": "^0.12.0",
"@jimp/jpeg": "^0.12.0",
"@jimp/png": "^0.12.0",
"@jimp/tiff": "^0.12.0",
"timm": "^1.6.1"
}
},
"@jimp/utils": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.10.3.tgz",
"integrity": "sha512-VcSlQhkil4ReYmg1KkN+WqHyYfZ2XfZxDsKAHSfST1GEz/RQHxKZbX+KhFKtKflnL0F4e6DlNQj3vznMNXCR2w==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.12.0.tgz",
"integrity": "sha512-MVoR31cQ6QRXHQI+qS9po7sr1LQTOOpQHE9I2oVeakcDkVX80xrRBif3WoNPvq3BG2+BDxt09CFwwHFHHFY49Q==",
"requires": {
"@babel/runtime": "^7.7.2",
"core-js": "^3.4.1",
"regenerator-runtime": "^0.13.3"
}
},
@ -2644,7 +2613,9 @@
"core-js": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.4.4.tgz",
"integrity": "sha512-vKea1DrcLA80Hrfc7AQgfoGvEaByfR5mH08t+zuWOWY94TFBmabdEL56mUbcijvadG9RxsXR2gUUFrfj4/iTcA=="
"integrity": "sha512-vKea1DrcLA80Hrfc7AQgfoGvEaByfR5mH08t+zuWOWY94TFBmabdEL56mUbcijvadG9RxsXR2gUUFrfj4/iTcA==",
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -2832,9 +2803,9 @@
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI="
},
"dayjs": {
"version": "1.8.26",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.26.tgz",
"integrity": "sha512-KqtAuIfdNfZR5sJY1Dixr2Is4ZvcCqhb0dZpCOt5dGEFiMzoIbjkTSzUb4QKTCsP+WNpGwUjAFIZrnZvUxxkhw=="
"version": "1.8.27",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.27.tgz",
"integrity": "sha512-Jpa2acjWIeOkg8KURUHICk0EqnEFSSF5eMEscsOgyJ92ZukXwmpmRkPSUka7KHSfbj5eKH30ieosYip+ky9emQ=="
},
"debug": {
"version": "4.1.1",
@ -3337,9 +3308,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"ejs": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.2.tgz",
"integrity": "sha512-zFuywxrAWtX5Mk2KAuoJNkXXbfezpNA0v7i+YC971QORguPekpjpAgeOv99YWSdKXwj7JxI2QAWDeDkE8fWtXw==",
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz",
"integrity": "sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==",
"requires": {
"jake": "^10.6.1"
}
@ -4448,9 +4419,9 @@
}
},
"file-type": {
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-14.3.0.tgz",
"integrity": "sha512-s71v6jMkbfwVdj87csLeNpL5K93mv4lN+lzgzifoICtPHhnXokDwBa3jrzfg+z6FK872iYJ0vS0i74v8XmoFDA==",
"version": "14.4.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-14.4.0.tgz",
"integrity": "sha512-U5Q2lHPcERmBsg+DpS/+0r+g7PCsJmyW+aggHnGbMimCyNCpIerLv/VzHJHqtc0O91AXr4Puz4DL7LzA5hMdwA==",
"requires": {
"readable-web-to-node-stream": "^2.0.0",
"strtok3": "^6.0.0",
@ -6114,9 +6085,12 @@
"integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4="
},
"is-wsl": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz",
"integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog=="
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"requires": {
"is-docker": "^2.0.0"
}
},
"is-yarn-global": {
"version": "0.3.0",
@ -6216,6 +6190,38 @@
}
}
},
"jasmine": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.5.0.tgz",
"integrity": "sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ==",
"dev": true,
"requires": {
"glob": "^7.1.4",
"jasmine-core": "~3.5.0"
},
"dependencies": {
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
}
}
},
"jasmine-core": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz",
"integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==",
"dev": true
},
"jest-worker": {
"version": "25.5.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz",
@ -6244,15 +6250,14 @@
}
},
"jimp": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/jimp/-/jimp-0.10.3.tgz",
"integrity": "sha512-meVWmDMtyUG5uYjFkmzu0zBgnCvvxwWNi27c4cg55vWNVC9ES4Lcwb+ogx+uBBQE3Q+dLKjXaLl0JVW+nUNwbQ==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/jimp/-/jimp-0.12.0.tgz",
"integrity": "sha512-8QD1QNk2ZpoSFLDEQn4rlQ0sDAO1z6UagIqUsH6YjopHCExcAbk3q2hJFXk6wSf+LMHHkic44PhdVTZ0drER2w==",
"requires": {
"@babel/runtime": "^7.7.2",
"@jimp/custom": "^0.10.3",
"@jimp/plugins": "^0.10.3",
"@jimp/types": "^0.10.3",
"core-js": "^3.4.1",
"@jimp/custom": "^0.12.0",
"@jimp/plugins": "^0.12.0",
"@jimp/types": "^0.12.0",
"regenerator-runtime": "^0.13.3"
}
},
@ -8231,9 +8236,9 @@
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="
},
"open": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/open/-/open-7.0.3.tgz",
"integrity": "sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA==",
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/open/-/open-7.0.4.tgz",
"integrity": "sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ==",
"requires": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"

View File

@ -18,7 +18,8 @@
"build-backend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js",
"build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js",
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
"webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js"
"webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js",
"test": "jasmine"
},
"dependencies": {
"async-mutex": "0.2.2",
@ -28,16 +29,16 @@
"commonmark": "0.29.1",
"cookie-parser": "1.4.5",
"csurf": "1.11.0",
"dayjs": "1.8.26",
"dayjs": "1.8.27",
"debug": "4.1.1",
"ejs": "3.1.2",
"ejs": "3.1.3",
"electron-debug": "3.0.1",
"electron-dl": "3.0.0",
"electron-find": "1.0.6",
"electron-window-state": "5.0.3",
"express": "4.17.1",
"express-session": "1.17.1",
"file-type": "14.3.0",
"file-type": "14.4.0",
"fs-extra": "9.0.0",
"helmet": "3.22.0",
"html": "1.0.0",
@ -51,11 +52,11 @@
"imagemin-pngquant": "8.0.0",
"ini": "1.3.5",
"is-svg": "4.2.1",
"jimp": "0.10.3",
"jimp": "0.12.0",
"mime-types": "2.1.27",
"multer": "1.4.2",
"node-abi": "2.16.0",
"open": "7.0.3",
"open": "7.0.4",
"portscanner": "2.2.0",
"rand-token": "1.0.1",
"rcedit": "2.1.1",
@ -82,6 +83,7 @@
"electron-builder": "22.6.0",
"electron-packager": "14.2.1",
"electron-rebuild": "1.11.0",
"jasmine": "^3.5.0",
"jsdoc": "3.6.4",
"lorem-ipsum": "2.0.3",
"webpack": "5.0.0-beta.16",

29
spec/lexer.spec.js Normal file
View File

@ -0,0 +1,29 @@
const lexerSpec = require('../src/services/search/lexer.js');
describe("Lexer", function() {
it("simple lexing", () => {
expect(lexerSpec("hello world").fulltextTokens)
.toEqual(["hello", "world"]);
});
it("use quotes to keep words together", () => {
expect(lexerSpec("'hello world' my friend").fulltextTokens)
.toEqual(["hello world", "my", "friend"]);
expect(lexerSpec('"hello world" my friend').fulltextTokens)
.toEqual(["hello world", "my", "friend"]);
expect(lexerSpec('`hello world` my friend').fulltextTokens)
.toEqual(["hello world", "my", "friend"]);
});
it("you can use different quotes and other special characters inside quotes", () => {
expect(lexerSpec("'I can use \" or ` or #@=*' without problem").fulltextTokens)
.toEqual(["I can use \" or ` or #@=*", "without", "problem"]);
});
it("if quote is not ended then it's just one long token", () => {
expect(lexerSpec("'unfinished quote").fulltextTokens)
.toEqual(["unfinished quote"]);
});
});

11
spec/support/jasmine.json Normal file
View File

@ -0,0 +1,11 @@
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}

View File

@ -1,7 +1,7 @@
const repository = require('./repository');
const sql = require('./sql');
const log = require('./log');
const parseFilters = require('./parse_filters');
const parseFilters = require('./search/parse_filters.js');
const buildSearchQuery = require('./build_search_query');
const noteCacheService = require('./note_cache/note_cache.js');

View File

@ -0,0 +1,15 @@
"use strict";
class NotExp {
constructor(subExpression) {
this.subExpression = subExpression;
}
execute(noteSet, searchContext) {
const subNoteSet = this.subExpression.execute(noteSet, searchContext);
return noteSet.minus(subNoteSet);
}
}
module.exports = NotExp;

View File

@ -0,0 +1,94 @@
function lexer(str) {
const fulltextTokens = [];
const expressionTokens = [];
let quotes = false;
let fulltextEnded = false;
let currentWord = '';
let symbol = false;
function isSymbol(chr) {
return ['=', '*', '>', '<', '!'].includes(chr);
}
function finishWord() {
if (currentWord === '') {
return;
}
if (fulltextEnded) {
expressionTokens.push(currentWord);
} else {
fulltextTokens.push(currentWord);
}
currentWord = '';
}
for (let i = 0; i < str.length; i++) {
const chr = str[i];
if (chr === '\\') {
if ((i + 1) < str.length) {
i++;
currentWord += str[i];
}
else {
currentWord += chr;
}
continue;
}
else if (['"', "'", '`'].includes(chr)) {
if (!quotes) {
if (currentWord.length === 0) {
quotes = chr;
}
else {
// quote inside a word does not have special meening and does not break word
// e.g. d'Artagnan is kept as a single token
currentWord += chr;
}
}
else if (quotes === chr) {
quotes = false;
finishWord();
}
else {
// it's a quote but within other kind of quotes so it's valid as a literal character
currentWord += chr;
}
continue;
}
else if (!quotes) {
if (chr === '#' || chr === '@') {
fulltextEnded = true;
continue;
}
else if (chr === ' ') {
finishWord();
continue;
}
else if (fulltextEnded && symbol !== isSymbol(chr)) {
finishWord();
currentWord += chr;
symbol = isSymbol(chr);
continue;
}
}
currentWord += chr;
}
finishWord();
return {
fulltextTokens,
expressionTokens
}
}
module.exports = lexer;

View File

@ -21,6 +21,18 @@ class NoteSet {
mergeIn(anotherNoteSet) {
this.notes = this.notes.concat(anotherNoteSet.arr);
}
minus(anotherNoteSet) {
const newNoteSet = new NoteSet();
for (const note of this.notes) {
if (!anotherNoteSet.hasNoteId(note.noteId)) {
newNoteSet.add(note);
}
}
return newNoteSet;
}
}
module.exports = NoteSet;

View File

@ -1,4 +1,9 @@
const dayjs = require("dayjs");
const AndExp = require('./expressions/and');
const OrExp = require('./expressions/or');
const NotExp = require('./expressions/not');
const NoteCacheFulltextExp = require('./expressions/note_cache_fulltext');
const NoteContentFulltextExp = require('./expressions/note_content_fulltext');
const filterRegex = /(\b(AND|OR)\s+)?@(!?)([\p{L}\p{Number}_]+|"[^"]+")\s*((=|!=|<|<=|>|>=|!?\*=|!?=\*|!?\*=\*)\s*([^\s=*"]+|"[^"]+"))?/igu;
const smartValueRegex = /^(NOW|TODAY|WEEK|MONTH|YEAR) *([+\-] *\d+)?$/i;