Parsers

sanity edited this page Apr 22, 2012 · 9 revisions

If you want to teach LastCalc how to parse something new, you need to subclass Parser.java, and then ensure it is added to the list of available parsers in Parser.java's getAll() method.

We'll use BoolParser.java as an example. Its task is to take a string that represents a boolean value, and turn it into a Java Boolean object.

Templates

The first thing to do is implement Parser's getTemplate() method. A template's job is to specify the type of token sequences that this parser will work on. This parser will only be attempted with TokenLists that match the template. This makes things more efficient because it means LastCalc doesn't try every Parser on every TokenList. BoolParser has a very simple template which consists of an array list of the four strings that might be boolean values, "true", "yes", "false", "no".

Templates can consist of multiple elements, so for example:

template = TokenList.createD("one", "two");

This template would only match a TokenList that contained the sequence "one", "two", in that order. We could also allow it to use numbers:

template = TokenList.createD(Lists.newArrayList("one", "un"), Lists.newArrayList("two", "deux"));

This would accept "one" or "two", and you could use either English or French - so the token list "one", "deux" would match this template.

You can also use Java Classes to indicate the Type of a value, rather than a string, so you could have:

template = TokenList.createD(Lists.newArrayList("one", "un"), Number.class);

This would match any TokenList that contained "one" or "un", followed by a Number object.

As you might expect, you can also have something like:

template = TokenList.createD(Lists.newArrayList("one", "un"), Lists.newArrayList(Number.class, String.class));

Here the second token could either be a Number or a String. You could also use Object.class which would match anything.

parse() method

Once you've got your template, which helps LastCalc efficiently find an appropriate parser to apply to a given TokenList, you can implement the part that actually does the transformation, by overriding Parser.parse():

public ParseResult parse(final TokenList tokens, final int templatePos) {

The parse method is called with the input TokenList, and the index within this list where the first element of the template matched. So, for example, with the template TokenList.createD("one", "two"), parse() might be called with tokens = ["dog", "one", "two", "cat"] and templatePos=1.

The parse method returns a ParseResult, which either indicates success, and contains the transformed token list (ParseResult.success(newTokenList)), or failure (ParseResult.fail()). Various methods on TokenList are useful here for constructing the transformed TokenList, in particular TokenList.replaceWithTokens(). This method returns a new TokenList where a sublist of tokens have been replaced.

See StringAppender for a simple example of a Parser implementation.

Lastly, to tell LastCalc about your new parser you need to add it to the Parser.getAll() method.