Cal Paterson
Cal Paterson

Reputation: 172

Why doesn't ANTLR recognise this rule the way I expect?

I'm using ANTLR to replace an existing (small) parser I currently have. Here is a snippet of the file I am trying to parse:

Lurker    915236167 10  2 Bk  cc    b     b         1000   70  200 Jc Qs
Lurker    915236237 10  1 Bc  kf    -     -         1130   10    0 
Lurker    915236302 10 10 c   c     rc    b         1120  110  305 6d Kd
Lurker    915236381 10  9 c   f     -     -         1315   20    0 
Lurker    915236425 10  8 cc  f     -     -         1295   30    0 

Here is Shared.g:

lexer grammar Shared;


NICK
    : LETTER (LETTER | NUMBER | SPECIAL)*
    ;

fragment
LETTER 
    : 'A'..'Z'
    | 'a'..'z'
    | '_'
    ;

NUMBER
    : ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')+
    ;

fragment
SPECIAL
    : ('-'|'^'|'{'|'}'|'|'|'['|']'|'`'|'\\')
    ;

WS  
    :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        )+
    ;

And Pdb.g:

grammar Pdb;
import Shared;

@header{
import java.util.ArrayList;
import java.sql.Connection;
}


@members{
    private Connection conn;

    private StringBuilder currentExpr = new StringBuilder(500);

    ArrayList<String> players = new ArrayList<String>(10);

    public void setConn(Connection conn){
        this.conn = conn;
    }
}

pdb
    : line+
    ;

line
    @after{
        currentExpr.append("execute player_handplan(");
        currentExpr.append($nick.text);
        currentExpr.append(", to_timestamp(");
        currentExpr.append(Integer.parseInt($timestamp.text));
        currentExpr.append("), ");
        currentExpr.append(Integer.parseInt($n_players.text));
        currentExpr.append(", ");
        currentExpr.append(Integer.parseInt($position.text));
        currentExpr.append(", ");
        currentExpr.append($action_p.text);
        currentExpr.append(", ");
        currentExpr.append($action_f.text);
        currentExpr.append(", ");
        currentExpr.append($action_t.text);
        currentExpr.append(", ");
        currentExpr.append($action_r.text);
        currentExpr.append(", ");
        currentExpr.append(Integer.parseInt($bankroll.text));
        currentExpr.append(", ");
        currentExpr.append(Integer.parseInt($total_action.text));
        currentExpr.append(", ");
        currentExpr.append(Integer.parseInt($amount_won.text));
        currentExpr.append(", ");
        currentExpr.append("CARDS");
        currentExpr.append(");");
        System.out.println(currentExpr.toString());
        currentExpr = new StringBuilder(500);
    }
    : nick=NICK WS
      timestamp=NUMBER WS
      n_players=NUMBER WS
      position=NUMBER WS 
      action_p=action WS
      action_f=action WS
      action_t=action WS
      action_r=action WS
      bankroll=NUMBER WS
      total_action=NUMBER WS
      amount_won=NUMBER WS
      (NICK WS NICK WS)? // ignore this
     ;

action
    : '-'
    | ('B'|'f'|'k'|'b'|'c'|'r'|'A'|'Q'|'K')+
    ;

My problem is, when I run the parser, I get the following error:

cal@lambda:~/src/DecisionTrees/grammar/output$ cat example | java Test 
line 1:26 no viable alternative at input 'Bk'
line 1:30 no viable alternative at input 'cc'
execute player_handplan(Lurker, to_timestamp(915236167), 10, 2, null, null, b, b, 1000, 70, 200, CARDS);

Why won't my grammar accept "Bk", even though it will accept "b"? I feel like there is something obvious I am overlooking. Thanks in advance

Upvotes: 0

Views: 310

Answers (1)

danny
danny

Reputation: 71

Why don't you use {$channel=HIDDEN} in rule WS and leave them out of the line rule.

That way at least you won't get in trouble for putting one too many WS by accident.

And if action can only have 2 chars max maybe trying this will help:

action
    : '-'
    | ('B'|'f'|'k'|'b'|'c'|'r'|'A'|'Q'|'K')('B'|'f'|'k'|'b'|'c'|'r'|'A'|'Q'|'K')?
    ;

Upvotes: 1

Related Questions