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

Commit

Permalink
Merge pull request #24 from abeaumont/improve-doc
Browse files Browse the repository at this point in the history
Improve doc
  • Loading branch information
abeaumont authored Sep 5, 2017
2 parents 3e81b1f + a9ffadd commit ef12cd5
Showing 1 changed file with 104 additions and 0 deletions.
104 changes: 104 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,110 @@ make install
make test
```

## Implementing the node interface

`libuast` is built to be easily bindable,
and to allow a native data structure for a [`Node`](https://godoc.org/github.com/bblfsh/sdk/uast#Node) in every language,
as provided by the protobuf generator.

That's why the library provides an interface to this `Node` data structure that must be implemented.
Concretely `NodeIface`, that is used to initialize the `Uast` struct:

```c
Uast *ctx = Node((NodeIface){
.InternalType = InternalType,
.Token = Token,
.ChildrenSize = ChildrenSize,
.ChildAt = ChildAt,
.RolesSize = RolesSize,
.RoleAt = RoleAt,
});
```

`NodeIface` holds the functions that need the be executed when the library needs to access some of the properties of the node, such as `internal_type`, `token`, `children`, ...

Here you can see several examples of the `Uast`:
- [C++ node](https://github.com/bblfsh/libuast/blob/master/tests/mock-node.h)
- [Python node](https://github.com/bblfsh/client-python/blob/master/bblfsh/pyuast.c)
- [Go node](https://github.com/bblfsh/client-go/blob/master/bindings.h)

Once the `Uast` context is created, it can be easily used to run xpath queries against the native nodes:

```c
// creating a Uast as explained above
Uast *ctx = CreateContextFromIface();

// get a c pointer to the native node
void *node = (void*)pointerToNativeNode;

// consume the Uast API (xpath in this case)
Nodes *nodes = UastFilter(ctx, node, "//NumLiteral")
```

### Running an xpath query

At this point, you might have already created your very first binding of libuast. Let's start playing with real stuff!

#### XPath querying

XPath allows to filter the whole UAST using the [xpath syntax](https://www.w3.org/TR/xpath/). It can be really useful to extract features from the code and thanks to the annotation system implemented by babelfish, it can be done in an universal fashion.


In libuast, xpath querying is performed by the `UastFilter` function. This function takes a pointer to the `Uast` context, a pointer to the root node, and the xpath query string.
The function returns a list of matching nodes.

Here's a complete example:
```c
const char *query = "//*[@roleImportDeclaration]";

// run the xpath query and check return value
Nodes *nodes = UastFilter(ctx, node, query);
if (nodes) {
// iterate over the results and print the nodes
for (int i = 0; i < NodesSize(nodes); i++) {
void *node = NodeAt(nodes, i);
print_node(node);
}
}

// do not forget to free the nodes afterwards.
NodesFree(nodes);
```
## Library internals
Internally UAST nodes are mapped to XML nodes in order to run xpath queries against them.
In _pseudo-xml_:
```xml
<{{internal_node}} role{{ROLE[n]}}> {{CHILDREN}} </{{internal_node}}>
```

As we can see, the `internal_type` (which is language-dependant) of the node is mapped as the tag-name while the roles are mapped as attributes of the element.

The roles are mapped as `role{{the role name in CamelCase}}`.

Examples:

- `SIMPLE_IDENTIFIER` -> `roleSimpleIdentifier`
- `IMPORT_DECLARATION` -> `roleImportDeclaration`


So, for example, to get all the number literals in Python, a filter to look for `NumLiteral` `internal_type` should work:

```python
xpath = "//NumLiteral"
```

But this is language dependant. To make it universal, roles should be used instead:

```python
xpath = "//*[@roleNumberLiteral]"
```

Look at [SDK documentation](https://godoc.org/github.com/bblfsh/sdk/uast#Role) for more information about roles.

## Contribute

Please follow [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html).

0 comments on commit ef12cd5

Please sign in to comment.