[antlr-interest] Seeking advice - 2 questions using ANTLR

Mark Volkmann r.mark.volkmann at gmail.com
Thu Jan 17 14:21:33 PST 2008


Here's a version of the grammar that I believe produces the output you
want. Note that it is currently limited to logical expressions with a
single "AND" or "OR". If anyone sees ways to improve what I've done
I'd love to get feedback on this. I'm still learning ANTLR.

grammar Accounting;

options {
  output = template;
}

@lexer::header { package com.ociweb.accounting; }
@parser::header { package com.ociweb.accounting; }

@parser::members {
  private void out(String text) { System.out.print(text); }
  private void outln(String text) { System.out.print(text); }
}

start: ifStatement EOF;

ifBegin: 'IF' { out("IF("); };
ifEnd: 'END IF' { out(")"); };

ifStatement
  : ifBegin condition 'THEN' statement ('ELSE' statement)? ifEnd;

comparison
  : expression RELATIONAL_OPERATOR expression;

condition
  : c1=comparison { out($c1.text); }
  | c1=comparison lo=LOGICAL_OPERATOR c2=comparison
    {
      out($lo.text + "(" + $c1.text + ", " + $c2.text + ")");
    }
  ;

expression
  : STRING_LITERAL
  | value (SIGN value)*
  ;

statement
  @init { out(", "); }
  : e=expression { out($e.text); }
  | ifStatement
  ;

value: NAME | NUMBER;

LOGICAL_OPERATOR: 'AND' | 'OR';

RELATIONAL_OPERATOR: '<' | '<=' | '=' | '>=' | '>';

APOSTROPHE: '\'';

NUMBER: INTEGER | FLOAT;
fragment FLOAT: INTEGER '.' NATURAL_NUMBER;
fragment INTEGER: SIGN? NATURAL_NUMBER;
fragment NATURAL_NUMBER: '0' | '1'..'9' '0'..'9'*;
SIGN: '+' | '-';

NAME: LETTER (LETTER | NUMBER | '_')*;

STRING_LITERAL: APOSTROPHE NONCONTROL_CHAR* APOSTROPHE;

WHITESPACE: (NEWLINE | SPACE)+ { $channel = HIDDEN; };

// Note that NONCONTROL_CHAR does not include the double-quote character.
fragment NONCONTROL_CHAR: LETTER | DIGIT | SYMBOL | SPACE;
fragment LETTER: LOWER | UPPER;
fragment LOWER: 'a'..'z';
fragment UPPER: 'A'..'Z';
fragment DIGIT: '0'..'9';
fragment NEWLINE: '\r'? '\n';
fragment SPACE: ' ' | '\t';

// Note that SYMBOL does not include the
// apostrophe or double-quote characters.
fragment SYMBOL: '!' | '#'..'&' | '('..'/' | ':'..'@' | '['..'`' | '{'..'~';


On Jan 17, 2008 3:55 PM, Mark Volkmann <r.mark.volkmann at gmail.com> wrote:
> Here's a start on your grammar.
>
> grammar Accounting;
>
> options {
>   output = template;
> }
>
> @lexer::header { package com.ociweb.accounting; }
> @parser::header { package com.ociweb.accounting; }
>
> start: ifStatement EOF;
>
> ifStatement
>   : 'IF' condition 'THEN' statement ('ELSE' statement)? 'END IF';
>
> comparison: expression RELATIONAL_OPERATOR expression;
>
> condition: comparison (LOGICAL_OPERATOR comparison)*;
>
> expression
>   : STRING_LITERAL
>   | value (SIGN value)*;
>
> statement: expression | ifStatement;
>
> value: NAME | NUMBER;
>
> LOGICAL_OPERATOR: 'AND' | 'OR';
>
> RELATIONAL_OPERATOR: '<' | '<=' | '=' | '>=' | '>';
>
> APOSTROPHE: '\'';
>
> NUMBER: INTEGER | FLOAT;
> fragment FLOAT: INTEGER '.' NATURAL_NUMBER;
> fragment INTEGER: SIGN? NATURAL_NUMBER;
> fragment NATURAL_NUMBER: '0' | '1'..'9' '0'..'9'*;
> SIGN: '+' | '-';
>
> NAME: LETTER (LETTER | NUMBER | '_')*;
>
> STRING_LITERAL: APOSTROPHE NONCONTROL_CHAR* APOSTROPHE;
>
> WHITESPACE: (NEWLINE | SPACE)+ { $channel = HIDDEN; };
>
> // Note that NONCONTROL_CHAR does not include the double-quote character.
> fragment NONCONTROL_CHAR: LETTER | DIGIT | SYMBOL | SPACE;
> fragment LETTER: LOWER | UPPER;
> fragment LOWER: 'a'..'z';
> fragment UPPER: 'A'..'Z';
> fragment DIGIT: '0'..'9';
> fragment NEWLINE: '\r'? '\n';
> fragment SPACE: ' ' | '\t';
>
> // Note that SYMBOL does not include the
> // apostrophe or double-quote characters.
> fragment SYMBOL: '!' | '#'..'&' | '('..'/' | ':'..'@' | '['..'`' | '{'..'~';
>
> It parses your example input except for I changed "H-CAPRESTATE" to
> "H_CAPRESTATE" to simply things. This way I can use "-" for
> subtraction. I'm sure there's a way to work this out so you can also
> use "-" in names.
>
> The grammar above doesn't output anything. It just verifies that input conforms.
>
> Email me privately if you want the Java code I wrote that uses the
> generated classes and my Ant build file.
>
>
> On Jan 17, 2008 3:02 PM, Mark Volkmann <r.mark.volkmann at gmail.com> wrote:
> > On Jan 17, 2008 2:04 PM, Frank Font <mrfont at room4me.com> wrote:
> > > Hello,
> > >
> > > I purchased the book, read through it, but I have a thick skull.
> > > Perhaps I can get some advice here on two questions about converting
> > > formula expressions that look like "basic" syntax...
> > >
> > > IF REP_DTE > '2001-01-01' AND ATOTAL>100 THEN
> > >     H-CAPRESTATE
> > > ELSE
> > >     IF REP_DTE < '2001-01-01' THEN
> > >         ACCTG_CNG + ACCTG_ERR_CRCT
> > >     END IF
> > > END IF
> > >
> > > Into a flat format that looks like Excel formula syntax...
> > >
> > > IF( AND(REP_DTE > '2001-01-01',ATOTAL>100), H-CAPRESTATE, IF(REP_DTE <
> > > '2001-01-01', ACCTG_CNG + ACCTG_ERR_CRCT)
> > >
> > > I tried writing a few grammar files, but all have had various runtime
> > > issues.
> > >
> > > Here are my questions...
> > >
> > > 1.  Is ANTLR the right tool for this job?  (I don't have much time.)
> >
> > ANTLR can definitely do this. However, you shouldn't expect the work
> > to go quickly if this is your first ANTLR grammar. You'll be learning
> > lots of things along the way.
> >
> > > 2.  If it is the right tool, is there already a grammar that will get me
> > > most of the way there?
> >
> > I'm not aware of a particular existing grammar that is close to what
> > you want. Maybe someone else knows of one.
> >
> >
> > > Thanks in advance for any advice.
> > >
> > > Regards,
> > > Frank Font
> >
> > --
> > R. Mark Volkmann
> > Object Computing, Inc.
> >
>
>
>
> --
> R. Mark Volkmann
> Object Computing, Inc.
>



-- 
R. Mark Volkmann
Object Computing, Inc.


More information about the antlr-interest mailing list