项目作者: dianpeng

项目描述 :
A small functional query language in Javascript to query tree structure data , ie Json,XML,CSV. Runs in Browser
高级语言: JavaScript
项目地址: git://github.com/dianpeng/seabird.git
创建时间: 2018-06-18T03:53:25Z
项目社区:https://github.com/dianpeng/seabird

开源协议:

下载


Seabird a tree structure query language

This is a rewrite of a tree query language I’ve written while at work. The one that I write
at work is not open source and implemented in C++ with some customize need. This version is a
rewrite of the tree query language that I have at work in Javascript.

Application

The library has a command line tool for doing interactive query. To use it, just need to use
your node like this node index.js "your_query". Then the result will be printted into the
console.

Language

1. Type

The language has a simple type system though it is weak type inheritedly. There’re several types :

  1. number (double)
  2. string
  3. null
  4. boolean
  5. list
  6. pair
  7. dict
  8. function
  9. user object

2. Grammar

The grammar itself is really similar to xpath but it is essentially a expression language. Any statement
inside of the language result in a value evaluated by the expression.

The query composes of 2 parts a let scope which is used to define variables or intermediate query results ;
and a expression serve as the main query.

Example:

  1. ## The let scope here defines one or multiple variables
  2. let data = file("my_file.json");# load a file content into memory
  3. let v = JSON(data) , # load data as JSON document
  4. d = v.**.Age[? this > 18]; # do a recursive search on all the *Age* field inside of JSON when the age field is
  5. # larger than 18
  6. # The main query, calculate the average age of all age that is large than 18
  7. avg(d);

As you can see the script assembles most of the curly bracket language’s expression feature with some specific
syntax added.

Here are simple basic example to show what we can do with the query:

  1. let json_data = file("json.file");
  2. let csv_data = file("csv.file");
  3. let json = JSON(json_data) , # load json
  4. csv = CSV (csv_data, " |,|;"), # load CSV, delimited by space or comma or semicolon
  5. d1 = json[1:100:2], # slice the array with start 1 , end 100 and stride 2
  6. d2 = json[0].field, # access a field called "field" in json object
  7. d3 = json.*[? (this.@value >= 13 && # apply filter on top of every direct child of object *Json*
  8. this.@value <= 15) || # the filter is indicated by [? filter-expression ]
  9. (this.@value * this.@value >= 100)],
  10. d4 = json.**[? type(this) == "number" && this == 10], # filter out all the number field with value 10, the "**"
  11. # indicates a recursive descent search
  12. d5 = 1+2*3-4 / d3[0], # do a normal arithmetic expression
  13. d6 = [1,true,false,null,{"AA":d1}], # generate a JSON document inline
  14. d7 = json.**[| this + 10 if type(this) == "number" else null ], # rewrite all the field that is number to be 10 more;
  15. # other types rewrite them to null
  16. d8 = group(d1,fn(x) "A" if(x.@size >10) else "B"), # do a group based on callback fn
  17. d9 = reduce(d8,fn(x) x.@size), # do a reduce
  18. d10 = fn(x) x if x <= 1 else fn(x-1) + fn(x-2), # write a fibonacci recursive function to be used later
  19. d11 = regex_match("more and more","/more/"); # do regex matching
  20. # output the final query result
  21. [
  22. csv,
  23. d1,
  24. d2,
  25. d3,
  26. d4,
  27. d5,
  28. d6,
  29. d7,
  30. d8,
  31. d9,
  32. d10(10), # calculate fibonacci number
  33. d11
  34. ]

For more example, please see query inside of the example.

3. Builtins

  1. type
  2. str
  3. num
  4. int
  5. list
  6. dict
  7. has
  8. new_regex
  9. regex_match
  10. sum
  11. avg
  12. min
  13. max
  14. substr
  15. trim
  16. split
  17. lower
  18. upper
  19. range
  20. genlist
  21. gendict
  22. filter
  23. map
  24. group
  25. reduce
  26. file

Browser

It is really easy to put the seabird library into the browser and run it entirely in the client.
I’ve tested it with Browserify. All you need to do is run command browserify browser.js -o seabird.js.
Then the whole library is in seabird.js. To use it here is an simple example

In your html page , write code load the library

  1. <script src='./seabird.js'> </script>

In your javascript file ,write following sample code:

  1. const obj = window.seabirdObject;
  2. const parser = window.seabirdParser;
  3. const eval = window.seabirdNewEvaluator;
  4. const printer= window.seabirdPrinter;
  5. let data = new obj.String("{\"Hello\":\"World\"}");
  6. // use global variable $ which later on will be passed into object Eval
  7. let ast = parser("JSON($).Hello");
  8. // new an evaluator , with first argument is a map of global variables and
  9. // second variable represents the dollar sign's data , here our data is a
  10. // string wrapper inside of obj.String. Notes, every normal Javascript
  11. // data needs to be wrapped as internal object representation.
  12. let e = eval({},data);
  13. // then do the evaluation and get the result
  14. let r = e.Eval();
  15. // then print the result out
  16. console.log( new printer.StrictJSON().Print(r) );

In browser, except builtin function file cannot be used, any other function works exactly the same.
And user can extend the library with new builtin functions or data models.

Extension

The library allows user to plugin any types of tree structure data for querying purpose. The builtin one supports JSON
and CSV style. But it is easy to wrap XML,Yaml or other tree structure data into the library for querying purpose.

License

MIT