Home
AddThis

Five minute introduction to ANTLR For Delphi Target

Five minute introduction to ANTLR For Delphi Target
Submitted by sharpplus on Wednesday, July 23, 2008 - 16:10

1. Get ANTLR For Delphi Target 3.1

 

After registering , You can get a download link of Antlr For Delphi Target.Download and Copy the files to some folder such as D:\antlr\310\lib, add all the jar to your classpath.

 

set classpath=D:\antlr\310\lib\stringtemplate-3.2.jar;D:\antlr\310\lib\antlr-runtime-3.1.jar;D:\antlr\310\lib\antlr-3.1.jar;D:\antlr\310\lib\antlr-2.7.7.jar

 

2. Create a simple grammar

 

grammar T;

 

options {

language=Delphi;

k=2;

}

prog : method ;

 

method

scope {

  String name;

}

    :   'method' ID '(' ')' {$method::name:=$ID.text;} body

    ;

 

body:   '{' stat* '}'

    ;

 

stat:   ID '=' expr ';'

    |   method // allow nested methods to demo stack nature of dynamic attributes

    ;

 

expr:   mul ('+' mul)*

    ;

 

mul :   atom ('*' atom)*

    ;

 

/** Demonstrate that 'name' is a dynamically-scoped attribute defined

 *  within rule method.  With lexical-scoping (variables go away at

 *  the end of the '}'), you'd have to pass the current method name

 *  down through all rules as a parameter.  Ick.  This is much much better.

 */

atom:   ID  {Writeln('ref '+$ID.text+' from method '+$method::name);}

    |   INT {Writeln('int '+$INT.text+' in method '+$method::name);}

    ;

 

ID  :   ('a'..'z'|'A'..'Z')+ ;

 

INT :   '0'..'9'+ ;

 

WS  :   (' '|'\t'|'\n'|'\r')+ {$channel:=HIDDEN;}

    ;

The following table list the difference between Delphi , Java Grammar.

 

Delphi

Java

Comment

options {

language=Delphi;

k=2;

}

options {

k=2;

}

 

language option tell antlr to generate Delphi Source for gramar

$channel:=HIDDEN;

$channel=HIDDEN;

Delphi Assign expression is ‘:=’, Java is ‘=’

 

 

3 Run ANTLR For Delphi Target on the simple grammar

 

under command line input following command

>>java org.antlr.Tool *.g

 

ANTLR will generate source files for the lexer and parser (e.g. TLexer.pas and TParser.pas).

 

4.Create a console project  named as Scope, and write a function to call the generated parser and lexer

 

program Scope;

 

{$APPTYPE CONSOLE}

 

uses

  SysUtils,

  Antlr,

  TLexer in 'TLexer.pas',

  TParser in 'TParser.pas';

 

procedure TestMain;

var

  input:ICharStream;

  lex:ITokenSource;

  tokens:ITokenStream;

  parser:TTParser;

 

begin

  //first load the file to be parsed

  input:=TAntlrFileStream.Create(ParamStr(1),'');

  //create a lexer to read from the input stream

  lex :=  TTLexer.CreateWithStream(input,nil);

  //create a token stream upon the lexer

  tokens := TAntlrCommonTokenStream.CreateWithSource(lex);

  //create parser to use the token stream

  parser := TTParser.CreateWithStream(tokens,nil);

 

  try

    try

      // call prog to execute the parse process

      parser.prog;

      Writeln('Press enter to terminate ...');

      Readln;

    except

      on E: Exception do

        Writeln(E.Classname, ': ', E.Message);

    end;

  finally

    parser.free;

  end;

end;

 

begin

  if ParamCount=0 then

    Writeln('Error:Please specify the input file name.'+sLineBreak

      +Format('Usage:%s input', [ExtractFileName(ParamStr(0))]))

  else

  begin

    if not FileExists(ParamStr(1)) then

      Writeln(Format('Error:Input file <%s> does not exists!', [ParamStr(1)]))

    else

      TestMain;

  end;

end.

 

5 Create the file with following content to be parsed

 

method foo() {

  i = 3;

  method bar() {

    j = i*2;

  }

  k = i;

}

 

save the file as input

 

6.Finally , Compile the project and run it .

 

>> Scope.exe input

 

the output will be

 

>>int 3 in method foo

>>ref i from method bar

>>int 2 in method bar

>>ref i from method foo

>>Press enter to terminate ...

 

This simple parser will print out all int values and referenced variables in function.

 

This is just a simple example , you can get all the source and grammar file from http://www.sharpplus.com/downloads/AntlrDelphiExamples.zip. The demo is under dynamic-scope folder.

 

7. Some minor difference between Java and Delphi target which is not include in above example

 

7.1 Container library

 

Java uses the default JDK Container library .

Delphi does not has a complete hash, set, list library in VCL, so we use the JCL Container library (you can download them from http://jcl.sourceforge.net which is MPL license).

 

7.2 embed user defined function to generated Delphi class.

 

unlike the java , in Delphi you need define the interface and implement par of class separately .For example , to add a function to java class, you could write it as

 

@members {

              boolean isTypeName(String name) {

                            for (int i = Symbols_stack.size()-1; i>=0; i--) {

                                          Symbols_scope scope = (Symbols_scope)Symbols_stack.get(i);

                                          if ( scope.types.contains(name) ) {

                                                        return true;

                                          }

                            }

                            return false;

              }

}

 

But in Delphi target ,you should write it as

 

@members {

function isTypeName(name:string):boolean;

}

 

 

@parser::membersImp{

function TCParser.isTypeName(name:string):Boolean;

var

  I:Integer;

  scope:TSymbols_scope;

begin

  for i := Symbols_stack.size()-1 downto 0  do

  begin

    scope := TSymbols_scope(Symbols_stack.get(i));

    if ( scope.types.contains(name) ) then

    begin

              Result:=true;

              Exit;

    end;

  end;

  Result:= false;

end;

}

 

8 To learn more about antlr

You could also:

 

    * Order The Definitive ANTLR Reference from the Pragmatic Programmers

    * Read the Antlr 3 Documentation at http://www.antlr.org

    * Chew on the Quick+Starter+on+Parser+Grammars

    * Browse the list of questions frequently asked about ANTLR 3

    * See other examples in our Demos package.



Poll

Syndicate
Syndicate content

(C) Copyright 2004-2014, SharpPlus Software Corp.