Parsing 我怎么能在雅阁里认出皮卡丘语?

Parsing 我怎么能在雅阁里认出皮卡丘语?,parsing,yacc,Parsing,Yacc,我正在尝试做一个简单的lex&yacc程序,可以识别皮卡丘的三种声音:皮、皮卡和皮卡丘。我唯一的规则是一个令牌不能在一行中出现3次。我试过这个: %token PI PIKA PIKACHU %% program : program line '\n' | ; line: PI piWords | PIKA pikaWords | PIKACHU pikachuWords ; piWords: PI | PI pikaWords | P

我正在尝试做一个简单的lex&yacc程序,可以识别皮卡丘的三种声音:皮、皮卡和皮卡丘。我唯一的规则是一个令牌不能在一行中出现3次。我试过这个:

%token PI PIKA PIKACHU

%%
program : program line '\n'
    |
    ;
line: PI piWords
    | PIKA pikaWords
    | PIKACHU pikachuWords
    ;
piWords: PI 
    | PI pikaWords
    | PI pikachuWords
    ;
pikaWords: PIKA 
    | PIKA piWords
    | PIKA pikachuWords
    ;
pikachuWords: PIKACHU
    | PIKACHU piWords
    | PIKACHU pikaWords
    ;
%%

但这并不适用于所有的组合,例如皮卡-皮卡丘-皮卡丘。我怎么能重写这个? 也尝试过限制lex中的标记,比如{0,2},但是当我写pi时,它仍然可以工作,即使它不应该工作。
更新。
基于下面的想法,我成功地完成了这项工作。我非常接近,我所需要的是保持跟踪,也有2次重复。我是这样做的:

program : program line '\n'
    |
    ;
line: piWords
    | pikaWords
    | pikachuWords
    ;
piWords: PI  
    | PI pikaWords
    | PI PI pikaWords
    | PI pikachuWords
    | PI PI pikachuWords
    ;
pikaWords: PIKA 
    | PIKA piWords
    | PIKA PIKA piWords
    | PIKA pikachuWords
    | PIKA PIKA pikachuWords
    ;
pikachuWords: PIKACHU
    | PIKACHU piWords
    | PIKACHU PIKACHU piWords
    | PIKACHU pikaWords
    | PIKACHU PIKACHU pikaWords
    ;

你的语法在正确的轨道上,但是需要一些调整


直观地说,每个非终结符都会跟踪您看到的最后一个终结符,这样就不允许同一个字符串在一行中出现两次。您可以通过让非终端跟踪以下信息来扩展这个想法:我最后看到的终端是什么,我看到了多少个副本?例如,当最后一个终端为PI时,有两个非终端,一个用于PI读取为第一个PI时,另一个用于PI读取为第二个PI时。根据到目前为止阅读的内容,思考产品如何在这些不同的非终端之间转换。

最后一个示例不接受两行完全相同的单词(除此之外没有其他内容),但这很容易添加。用左递归形式编写也会更有效(右递归规则使用更多的堆栈空间)。。你能给我举个例子,说明我如何使用左递归形式来实现这一点吗?只要颠倒所有这些规则的RHS顺序。。。