wheresrhys/keen-query

DSL grammar

Closed this issue · 3 comments

Would make the parser less brittle

https://medium.com/@jbscript/intro-to-peg-js-writing-parsers-for-custom-dsls-28376a081e1b#.g6mw64667

Need to write a secondary parser for parsing filters and function bodies in general

Consider using http://shamansir.github.io/pegjs-fn/ - smaller file output, more readable and easier to debug? But slower (though query parsing probably isn't the bottleneck ever)

start = generalisedQuery

generalisedQuery = ws body:( ntupleAggregator / binaryAggregator / unaryAggregator / simpleQuery ) ws { return body }

generalisedQueries = q1:generalisedQuery qn:(nthGeneralisedQuery+) { return [q1].concat(qn)}

nthGeneralisedQuery = "," q:generalisedQuery {return q}

ntupleAggregator = "@" name:ntupleAggregatorName "(" qs:generalisedQueries ")" functions:(function*) {
  return {
    aggregator: name,
    queries: qs,
    functions: functions
  }
}

binaryAggregator = "@" name:binaryAggregatorName "(" q1:generalisedQuery "," q2:generalisedQuery ")" functions:(function*) {
  return {
    aggregator: name,
    queries: [q1, q2],
    functions: functions
  }
}

unaryAggregator = "@" name:unaryAggregatorName "(" q:generalisedQuery ")" functions:(function*) {
  return {
    aggregator: name,
    queries: [q],
    functions: functions
  }
}

ntupleAggregatorName = "concat" / "funnel"

binaryAggregatorName = "sum" / "ratio" / "pct"

unaryAggregatorName = ""

simpleQuery = collection:collection functions:(function*) {
   return {
     event: collection,
     functions: functions
   }
}

collection = word (":"word)? { return text()}

function = ws "->" name:functionName body:functionBody {return {name:name, body: body}}

functionName = "print" / "count" / "min" / "max" / "sum" / "avg" / "median"
        / "percentile" / "select" / "filter" / "interval" / "group" / "tidy"
        / "relTime" / "absTime" / "reduce" / "round" / "sort" / "multiply"
        / "divide" / "sortAsc" / "sortDesc" / "sortProp" / "plotThreshold"
        / "relabel" / "top" / "bottom" / "cutoff" / "with"

functionBody = "(" ws body:(notClosingParentheses*) ws ")" {return body.join('')}

notClosingParentheses = ![)] text: . {return text}

word = letter+ {return text()}

letter = [a-zA-Z]

ws = [ \t\n\r]* {return}

Addressed in #113