Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Create Domain-Specific Languages with ANTLR : Page 5

The latest version of ANTLR provides the tools you need to build a parser for special-purpose languages.

Tree Walkers
With a simplified version of the SPARQL query in place in the form of an AST, it's time to do something useful with it. As mentioned previously, you can use tree walkers to further process ASTs and take actions such as emitting output. Tree walkers are parsers that take ASTs as input. As such, defining them is extremely similar to defining the parsers you've already seen. Here's an example:

// src/main/antlr/com/devx/sparql/SparqlWalker.g tree grammar SparqlWalker; options { ASTLabelType=CommonTree; tokenVocab=Sparql; output=template; }

The preceding snippet defines a tree walker named SparqlWalker, which takes trees as input and creates templates as output. This walker is configured to re-use the token vocabulary defined for the parser. This reuse is important, because the expression of the shared AST needs to be consistent between the parser and the walker. Because the walker cannot be generated correctly until after the parser has been generated, you need to bind a separate execution of the ANTLR Maven plug-in to the generate-sources phase of the Maven build. You can see an example in the downloadable source.

Given the AST shown in Figure 4, a rule to walk the AST representation of a triple might look like this:

triple : ^( TRIPLE s=element p=element o=element ) ; element : QUESTION_VARNAME | DOLLAR_VARNAME ;

Notice that the input the walker is recognizing matches the output of the parser. The examples that follow use the String Template framework to emit prettified SPARQL. String Template is closely related to the ANTLR project and is tightly integrated with ANTLR itself. Instead of creating an AST, tree walkers can output StringTemplates. StringTemplates can be populated with attributes from the grammar and can render output by substituting these attributes into a textual template description. For example, the code below captures the text of an element in an attribute and renders the text into a simple string using an anonymous template:

element : QUESTION_VARNAME -> template( name = {$QUESTION_VARNAME.text} ) "$name$" | DOLLAR_VARNAME -> template( name = {$DOLLAR_VARNAME.text} ) "$name$" ;

The template keyword following the arrow identifies an anonymous template to use to render the output. You define anonymous templates inside quoted strings following the template definition. In the example above, this template reads "$name$". In the example, if the text of the matching QUESTION_VARNAME token was ?s, then the output of this template would be simply ?s. That's a pretty basic example; here's one that's slightly more interesting—the triple itself:

triple : ^( TRIPLE s=element p=element o=element ) -> triple( subject={$s.st}, predicate={$p.st}, object={$o.st} ) ;

The fragment above refers to a named template, triple. This template is populated with three attributes, each of which is the result of evaluating another template—the anonymous template from the element rule. The triple template is defined separately from the walker grammar. In the full example this file is named sparql.stg (STG stands for String Template Group). The file contains definitions for each template referenced in the grammar. The definition for the triple template is simple:

// src/main/resources/templates/sparql.stg triple(subject, predicate, object) ::= << $subject$ $predicate$ $object$ . >>

The text between the << and >> delimiters is the basic output of the template. You substitute attributes into the output by wrapping them with dollar signs as shown in the example above. HTML is one possible output medium for prettified SPARQL. HTML allows you to decorate different types of text by defining and applying styles. For example, the following templates prepare a basic HTML page for a query and assign a CSS class named clause to each SELECT clause, which causes them to appear in purple.

query(selectClause, whereClause) ::= << <html> <head> <TITLE>CSS Example</TITLE> <STYLE TYPE="text/css"> .sparql { font-family: monospace; font-size: large; } .clause { color: purple; } </STYLE> </head> <body class="sparql"> $selectClause$<br> $whereClause$ </body> </html> >> selectClause(element) ::= << <span class="clause">SELECT</span> $element$ >>

Lastly, to prettify the SPARQL further, each WHERE clause should be indented and separated by a line break. The following walker rule populates the whereClause attribute with triples from a SPARQL query.

whereClause : ^( WHERE triples+=triple+ ) -> whereClause( triples={$triples} ) ;

What's different here is that the walker rule populates the triples attribute with a list of StringTemplates. The template for this construct is:

whereClause(triples) ::= << <span class="clause">WHERE</span><br> {<br> &nbsp;&nbsp;&nbsp;&nbsp;$triples; separator="<br>\n&nbsp;&nbsp;&nbsp;&nbsp;"$<br> } >>

Notice the $triples; separator=""$ construct, which specifies how to separate each element of the list. The StringTemplate supports auto-indentation of whitespace, but unfortunately the escaped representation of a space in HTML ( ) isn't whitespace itself—so the sample application doesn't capitalize on this feature.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.