Subscribe (RSS)

Quick Links

About Actipro

Actipro Software has been creating .NET user interface control products for Windows Forms since its inception. More recently, Actipro has become a pioneer in the .NET 3.0 WPF control development arena.

SyntaxEditor for WPF to add integration with ANTLR parsers

by Bill Henning (Actipro) August 11, 2009 at 10:08

We’re very excited to officially announce that the next build of WPF Studio will contain a new assembly that makes it easy to automatically call an ANTLR-generated parser via worker threads whenever SyntaxEditor document text changes.  This new assembly will be included free for use by any of our SyntaxEditor for WPF customers.

What is ANTLR?

ANTLR, ANother Tool for Language Recognition, was created by Terence Parr and is one of the most widely-used parsing frameworks available.  ANTLR is a framework for constructing recognizers, interpreters, compilers, and translators from grammatical descriptions containing actions in a variety of target languages. ANTLR provides excellent support for tree construction, tree walking, translation, error recovery, and error reporting.

New Sample to Demonstrate ANTLR Add-on

We’ve built a new sample project that demos a calculator parser generated by ANTLR.  This new sample project will be in the next WPF Studio build.

AntlrSample

The sample has a SyntaxEditor instance at the lower left.  You can enter a simple integer mathematic equation into the editor.  When text changes occur, SyntaxEditor uses its advanced parsing framework to call an ANTLR parser in a worker thread.  The parser returns its AST result back to the document asynchronously when it completes. 

In the sample, the AST result is loaded into a WPF TreeView.  It even calculates and displays the result!

This is a rather simplistic use of ANTLR but we wanted to show the base concept of how our new add-on works.  It’s just as easy to call any other more complicated ANTLR parser, such as ones for C++, Javascript, etc.

How Does the Add-on Work?

It’s actually very simple.  For the sample above, we made an ANTLR grammar called AntlrCalc.g and used it to generate two classes:  AntlrCalcLexer and AntlrCalcParser.  Next we included those classes in our project.

Now it’s time to use the new add-on to wrap the AntlrCalcParser (via our add-on’s AntlrParser class) and register the AntlrParser as an IParser for the language:

   1: // Construct a SyntaxLanguage based on the ANTLR parser by 
   2: //   using the Actipro ANTLR add-on
   3: SyntaxLanguage language = new SyntaxLanguage("Calc");
   4: language.RegisterService<IParser>(
   5:     new AntlrParser(
   6:         language.Key, 
   7:         typeof(AntlrOutput.AntlrCalcLexer), 
   8:         typeof(AntlrOutput.AntlrCalcParser), 
   9:         "expr"
  10:         ));
  11:  
  12: // Assign the SyntaxLanguage to the SyntaxEditor's document
  13: this.syntaxEditor.Document.Language = language;

The AntlrParser class takes four constructor parameters:  a string key that identifies the parser's language, the Type of core ANTLR lexer and parser, and the root rule name in the core ANTLR parser to execute.  In our ANTLR grammar, the root rule is called expr.

Once our AntlrParser is registered with the language as an IParser and the language is assigned to a document, any changes made to that document (via an attached SyntaxEditor for instance) will cause the ANTLR parser to be run.  Its result is passed back in an IAntlrParseData object to the document’s ParseData property.  This triggers the document’s ParseDataChanged event, so that listeners can know that the parse data was updated.

SyntaxEditor Embraces Third-Party Solutions

With the addition of the ANTLR add-on, we now have two free add-ons that support integration with third-party parsing frameworks.  The first one packaged with SyntaxEditor works with Microsoft’s MGrammar, and now we have dedicated support for Terence Parr’s ANTLR as well.

Just because we don’t have dedicated add-ons for other parsing frameworks doesn’t mean they can’t be used with SyntaxEditor as well.  All these two add-ons do is provide a bridge between the Actipro text/parsing framework and the third-party parser framework.  So if you use another third-party parsing framework, they can be wired up fairly easily with a little bit of coding.

Comments

August 10, 2009 at 04:10  

trackback

SyntaxEditor for WPF to add integration with ANTLR parsers

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetKicks.com

August 10, 2009 at 06:50  

Scott Currie

I thought I'd call out another scenario, which is similar to this one.  We currently use your XML parser service.  While our language is XML-based, we do a lot of our own custom parsing to map the language onto a custom AST with application specific capabilities.  

When you implement this bridge code for your own XML parsing framework, it would be really great for us if you provided a hook that we could use to call our supplemental parsing code.  Even better would be if you could attach multiple IParsers to do background parses on the same document.  That way, neither our parser or your XML parser would block on each other.  Please email me if you'd like to discuss the scenario in more detail.

Thanks,
-Scott

Scott Currie United States

August 11, 2009 at 03:18  

Bill Henning (Actipro)

Scott,

Actually with the current design it would be very easy to "chain" together multiple IParser instances.  I don't think it would be possible to execute multiple parsers on separate threads at the same time however sequentially chaining them is certainly possible.

Say once we eventually have our advanced XML language done.  You'd create an instance of our add-on's XML language.  Then you'd call language.GetService<IParser>() to get our IParser implementation.  You'd make a custom class that implements IParser.  In the constructor to that class you'd pass in the IParser instance that you got from our language.  Then in your parser's Parse method, first you'd call our existing parser's Parse method directly, followed by executing your logic.  You'd register your custom IParser in place of the one we have in the language by default.  Thus, you have achieved the chaining of two IParsers, where your custom one calls ours first and runs your code second, but still in the worker thread.

Hope that helps!

Bill Henning (Actipro) United States

September 30, 2009 at 21:41  

trackback

Actipro Blog 2009 Q3 posting summary

Actipro Blog 2009 Q3 posting summary

The Actipro Blog - WPF and WinForms Development

Comments are closed