Let user type SQL-like queries.
<COLUMN> <KEYWORD> <ARGS>
↓
[<COLUMN, ID> <KEYWORD, EQL> <ARG, 3>]
↓
Letter = 'A' / 'B' / … / 'Z'
Digit = [0-9]
Integer = Digit Integer / Digit
<Name> = [A-Z] [a-z]+
<Name> = [A-Z] <Letters>
<Name> = [A-Za-z] <Name>
<name, attribute>
<COLUMN, "Id">
<KEYWORD, "=">
<ARG, 1>
Start = Term
Digit = [0-9]
Sign = '-' / '+'
Term = Digit Sign Term / Digit
2 + 3 - 4
let result = [];
let curIndex = 0;
const descend = (input) => {
term(input);
return result;
}
const term = (input) => {
result.push(['term']);
digit(input);
if (input[curIndex + 1]) {
sign(input);
term(input);
}
}
const sign = (input) => {
const curChar = input[curIndex];
if (isSign(curChar)) {
result.push(['sign', curChar])
curIndex += 1;
} else {
throw new
SyntaxError(`${curChar||'∅'}\
instead of sign`); } }
const isSign = (c) =>
['+', '-'].includes(c)
const isDigit = (c) =>
'0123456789'
.split('')
.includes(c);
const parsed = JSON.stringify(descend("2+3-4"))
console.log('parsed: ', parsed)
// parsed: [["term"],["digit","2"]
// ["sign","+"],["term"],["digit","3"]
// ["sign","-"],["term"],["digit","4"]]
npm i pegjs chokidar-cli
// in package.json scripts
chokidar 'parens.pegjs'
--initial
--silent
-c 'pegjs -o
parens-parser.js
parens.pegjs'
.
- any char*
/ +
/ ?
/ ()
start = group
lpar = '('
rpar = ')'
nothing = ''
group =
lpar group rpar
/ group group
/ ''
group =
lpar group rpar
/ group group
/ ''
group = lpar rest
/ lpar group rpar
/ ''
rest = ')' group
/ ')'
start = FLOAT
SIGN = "-" / "+"
DIGIT = [0-9]
INTEGER =
d:DIGIT int:INTEGER
{ /* other side effect */
return d + int }
/ d:DIGIT
{ return d }
{
const notNull = (thing) =>
thing != null
}
parser.parse(string, options);
FLOAT = sign:SIGN?
whole:INTEGER? "."?
fraction:INTEGER? &{
return notNull(whole)
|| notNull(fraction)
}
{ return { sign,
whole,
fraction } }
"ID" >= (20)
ID less than 20
// level2 * /
// level1 + -
start = level1
level1 =
level2 ([+-] level2)+
/ level2
level2 =
level0 ([*/] level0)+
/ level0
level0 = number / "(" level1 ")"
number = [0-9]+
{
column: { name, location, type }
keyword: { value, location }
argument: [ { value, location }]
}
{
complete: true,
sequence: [
{ column: { name, location, type }},
{ whitespace: true },
{ keyword: { value, location, type }},
{ whitespace: true },
{ argument: [{ value, location }]}
]
}
ID =
is a valid expression
progressiveExpression =
column:column whitespace keyword:keyword whitespace* argument:inprogArgumentList
{ return { complete: false, sequence: [makeColumn(column), makeWhitespace(),
makeKeyword(keyword), makeWhitespace(), makeArgument(argument) ] }}
/ column:column whitespace keyword:keyword whitespace+
{ return { complete: false, sequence: [makeColumn(column), makeWhitespace(),
makeKeyword(keyword), makeWhitespace()] }}
… 3 redacted
/ column:column { return { complete: false, sequence: [makeColumn(column)] }}
/ inprogColumn
inprogEntity '' = …
equalOp = ['equal']i 's'i?