[antlr-interest] Problems customizing tree construction

Mark Wright markwright at internode.on.net
Wed Jul 30 09:29:24 PDT 2008


On Wed, 30 Jul 2008 15:54:30 +0200
"Mathilde GUERIN" <mathilde.guerin at gmail.com> wrote:

> I've already looked into this approach but it wouldn't solve my
> problem (or at least, I don't think so...): in my project, the
> variables that compose a group have to be represented as child nodes
> of the group node:
> 
>  |-#GROUPB        (level=1)  <ASTGroup>
>      |-#FIELDB-A  (level=2)  <ASTVariable>
>      |-#FIELDB-B  (level=2)  <ASTVariable>
> 
> From what I gathered from the symbol table articles that I read, I
> wouldn't be able to do that with this approach... right?
> 
> ~MG~

Hi,

Some ideas:

(1) You could create a structure like what you have above
in a symbol table instead of in the AST.  Of course you will
need to figure out if you want to do that or not.

With the symbol table approach, you could add actions to the
grammar to set the current scope, and add the variables to
the current scope.  Something like:

@members {
  SemanticActions sa;
}
grammar 
    : (groupDefinition | varDefinition)+ ;
groupDefinition
    : INT ID endLine+
      { sa.groupDefinition($INT, $ID); }
      -> ^(ID<ASTGroup>[$INT.level]) ;
varDefinition
    : INT ID format endLine+
      { sa.varDefinition($INT, $ID); }
      -> ^(ID<ASTVariable>[$INT.level] format) ;

And in the SemanticActions.groupDefinition() you can call something
like a moveIntoGroupDefinitionScope(scopeLevel, group) method.

And in SemanticActions.varDefinition(), you can look up the
current scope, then enter the var definitions into the
group variable found from the scope lookup.

So of course you can create a symbol table data structure that
looks like the AST you asked for.

(2) Alternatively, if you want an AST like that, then one crazy idea
is as follows.  I say its crazy because it seems kind of complicated,
I wonder if there might be an easier way to do it than my suggestion
here.  I don't know if something like this can be made to work either.

You can create your own AST and Token classes, which are in
a relationship with each other, something like:

import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.Token;
import org.antlr.runtime.CommonToken;
import tntdbo.sym.Symbol;

public class MyAST extends CommonTree {
    public MyAST(Token t) {
        super(t);
        t.setAST(this);
    }

    public MyAST(int ttype, String text) {
        Token t = new CommonToken(ttype, text);
        super(t);
        t.setAST(this);
    }
}

The varDefinition action can dynamically create the returned AST,
something like:

@members {
  SemanticActions sa;
}
@lexer::members {
    public Token emit() {
        Token t = new MyToken(input, state.type, state.channel, state.tokenStartCharIndex, getCharIndex()-1);
        t.setLine(state.tokenStartLine);
        t.setText(state.text);
        t.setCharPositionInLine(state.tokenStartCharPositionInLine);
        emit(t);
        return t;
    }
grammar 
    : (groupDefinition | varDefinition)+ ;
groupDefinition
    : INT ID endLine+
      { sa.groupDefinition($INT, $ID); }
      -> ^(ID<ASTGroup>[$INT.level]) ;
varDefinition
    : INT ID format (e+=endLine)+
      -> { sa.varDefinition(adaptor, $INT, $ID, $format, $e); }

And the method would be something like:

public CommonTree varDefinition(TreeAdaptor adaptor, Token level, Token id,
                                 List endLineTokenList) {
  CommonTree groupAST = lookupController.lookup(level, id);
  adaptor.addChild(groupAST, (CommonTree)adaptor.create(level));
  return ast;
}

Its kind of a sketch, not sure if something like this would really
work or not.

Regards, Mark

-- 


More information about the antlr-interest mailing list