为什么 ANTLR 没有按照我期望的方式识别这条规则?

发布于 2024-10-01 20:25:12 字数 3275 浏览 1 评论 0原文

我正在使用 ANTLR 来替换我目前拥有的现有(小型)解析器。这是我尝试解析的文件的片段:

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 

这是 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'
        )+
    ;

和 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')+
    ;

我的问题是,当我运行解析器时,出现以下错误:

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" ,即使它会接受“b”?我觉得有一些明显的东西被我忽略了。提前致谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鹿童谣 2024-10-08 20:25:13

为什么不在规则 WS 中使用 {$channel=HIDDEN} 并将它们排除在线路规则之外。

这样至少您不会因为意外放置太多 WS 而遇到麻烦。

如果操作最多只能有 2 个字符,也许尝试这会有所帮助:

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

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')?
    ;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文