Skip to content
This repository has been archived by the owner on Mar 8, 2020. It is now read-only.

Latest commit

 

History

History
173 lines (126 loc) · 4.6 KB

clients.md

File metadata and controls

173 lines (126 loc) · 4.6 KB

Clients

There are some clients in different languages that provide a higher level API, built on top of gRPC and libuast.

These clients make it easier to both parse and analyze the resulting UAST, abstracting from network communication and providing a query language to filter UASTs and can be used both as a library or as command line programs.

Existing clients

There are clients for the following languages:

Language Status UAST.v2 / libuast.v3 URL
Python Beta bblfsh/python-client
Go Beta bblfsh/go-client
Scala WIP bblfsh/client-scala

Examples

The client API's differ to adapt to their language specific idioms, the following code snippets show several simple examples with the Go, Python and Scala clients that parse a file and apply a filter to return all the simple identifiers:

Go example

As a command, using bblfsh-cli:

bblfsh-cli -q [XPath query] -m semantic [file.ext]

As a library:

package main

import (
	"context"
	"fmt"
	"time"

	bblfsh "github.com/bblfsh/go-client/v4"
	"github.com/bblfsh/go-client/v4/tools"
	"github.com/bblfsh/sdk/v3/uast"
	"github.com/bblfsh/sdk/v3/uast/nodes"
)

func main() {
	client, err := bblfsh.NewClientContext(context.Background(), "localhost:9432")
	if err != nil {
		panic(err)
	}
    defer client.Close()

	res, _, err := client.NewParseRequest().ReadFile("some_file.py").UAST()
	if err != nil {
		panic(err)
	}

	it, err := tools.Filter(res, "//*[not(@token = '') and not(@role='Qualified')]")
	if err != nil {
		panic(err)
	}
	for it.Next() {
		// Print the internal type
		n := it.Node()
		fmt.Printf("Type: %q (%T)\n", uast.TypeOf(n), n)

		node, ok := n.(nodes.Object)
		if !ok {
			continue
		}

		// Print the positions
		pos := uast.PositionsOf(node)
		fmt.Println("StartPos:", pos.Start(), " EndPos:", pos.End())

		// Print the token
		fmt.Println("Token:", uast.TokenOf(node))
	}

	// Get the normalized identifiers
	it, err = tools.Filter(res, "//uast:Identifier")
	if err != nil {
		panic(err)
	}
	for it.Next() {
		node, ok := it.Node().(nodes.Object)
		if !ok {
			continue
		}
		fmt.Println(node["Name"])
	}
}

Python example

As a command:

python3 -m bblfsh -q [XPath query] -f [file.ext]

As a library:

import bblfsh

if __name__ == "__main__":
    client = bblfsh.BblfshClient("0.0.0.0:9432")
    ctx = client.parse("some_file.py")

    it = ctx.filter("//uast:Identifier")
    for n in it:
        print(n.get())

Scala example

As a command:

java -jar bblfsh-client-assembly-1.0.1.jar -q [XPath query] -f file.py

As a library:

import org.bblfsh.client.BblfshClient._

import gopkg.in.bblfsh.sdk.v1.protocol.generated.ParseResponse
import gopkg.in.bblfsh.sdk.v1.uast.generated.Node

import scala.io.Source

class BblfshClientParseTest {
  val fileName = "src/test/resources/SampleJavaFile.java"
  val fileContent = Source.fromFile(fileName) .getLines.mkString

  val resp = client.parse(fileName, fileContent)

  if (resp.uast.isDefined) {
     rootNode = resp.uast.get
     val filtered = client.filter(rootNode, "//*[@role='Identifier' and not(@role='Qualified')]")
     filtered.foreach{ println }
  } else {
    // ... handle resp.uast.errors
  }
}

Query language

When using one of the clients that support libuast you can query the UAST result nodes using an xpath-like query language. Check the UAST querying page in this documentation for the details.

Iterators

The client also allows you to instance an Iterator object and iterate over the tree on several predefined orders:

To check the exact way to use an iterator you must consult the readme of the specific client you're using, but they're generally easy to use as this Python example shows:

import bblfsh
client = bblfsh.BblfshClient("0.0.0.0:9432")
root = client.parse("/path/to/myfile.py")

for node in bblfsh.iterator(root, bblfsh.TreeOrder.PRE_ORDER):
    #... do stuff with the node