0

私はこのyaccファイルを持っています

%error-verbose
%token  END
%token  ID
%token  INT
%token  IF
%token  ELSE
%token  WHILE
%token  FOR
%token  BREAK
%token  CONTINUE
%token  RETURN
%token  SEM
%token  LPAR
%token  RPAR
%token  PLUS
%token  MINUS
%token  MULT
%token  DIV
%token  MOD
%token  GT
%token  LT
%token  GTE /* >= */
%token  LTE /* <= */
%token  EQUAL   /* == */
%token  NEQUAL  /* != */
%token  AND
%token  OR
%token  EQ
%token  COM
%token PRINT 
%token READ
%token FLOAT
%token LABR
%token RABR
%token NUM
%token STR


/*
 *  precedentce tabLTE
 */

%right  EQ PE ME TE DE RE
%left   OR
%left   AND
%left   EQUAL NEQUAL
%left   LT GT GTE LTE
%left   PLUS MINUS
%left   MULT DIV MOD
%right  PP MM
%{
#include<stdio.h>
extern char *yyname;
extern char *yytext;
extern int yylineno;
void yyerror(char const *msg)
{
fprintf(stderr,"%s:%d:%s\n", yyname,yylineno,msg);

}
%}
%%
program
    : definitions
    ;
definitions
    : definition
    | definitions definition
    ;
definition:
    | declaration
    ;
declarations
    : /* null */
    | declarations declaration
    ;
declaration
    : INT declarator_list SEM
    ;

declarator_list
    : ID
    | declarator_list COM ID
    ;
statements
    : /* null */
    | statements statement
    ;
statement
    : expression SEM
    | SEM   /* null statement */
    | if_prefix statement
    | if_prefix statement ELSE statement
    | loop_prefix statement
    ;
if_prefix
    : IF LPAR expression RPAR
    ;
loop_prefix
    : WHILE LPAR expression RPAR
    ;
expression
    : binary
    | expression COM binary
    ;
binary
    : ID
    | LPAR expression RPAR
    | ID LPAR optional_argument_list RPAR
    | binary PLUS binary
    | binary MINUS binary
    | binary MULT binary
    | binary DIV binary
    | binary MOD binary
    | binary GT binary
    | binary LT binary
    | binary GTE binary
    | binary LTE binary
    | binary EQUAL binary
    | binary NEQUAL binary
    | binary AND binary
    | binary OR binary
    | ID EQ binary
    | ID PE binary
    | ID ME binary
    | ID TE binary
    | ID DE binary
    | ID RE binary
    ;
optional_argument_list
    : /* no actual arguments */
    | argument_list
    ;
argument_list
    : binary
    | argument_list COM binary
    ;

%%

#include <stdlib.h>
extern FILE *yyin;
int main(int argc, char **argv)
{
    int ok;
    if (argc != 2) {
        fprintf(stderr, "%s: Wrong arguments\n", argv[0]);
        return EXIT_FAILURE;
    }
    yyname = argv[1];
    if ((yyin = fopen(yyname, "r")) == NULL) {
        fprintf(stderr, "%s: %s: Invalid file\n", argv[0], argv[1]);
        return EXIT_FAILURE;
    }
    return (yyparse() ? EXIT_SUCCESS : EXIT_FAILURE);
}

入力が int x の場合。すべて正常に動作しますが、入力が "INT" 以外の場合、FOR はエラーをスローします。予期しない FOR は INT または $end を期待しているため、実際には一連のルールから最初のルールのみを読み取っています。さらに、表示され続けます。 bison コマンドを適用すると、無駄な非端末と端末の警告が表示されます。

この yacc ファイルの何が問題になっていますか?

4

2 に答える 2

2

問題は、ルールが次のとおりであることです。

program
    : definitions
    ;
definitions
    : definition
    | definitions definition
    ;
definition:
    | declaration
    ;
declarations
    : /* null */
    | declarations declaration
    ;
declaration
    : INT declarator_list SEM
    ;

宣言のみを許可します。statementsの一部として何も許可されませんprogram。FOR は宣言ではないため、文法で拒否されます。

「役に立たない非端末」警告は、次のことを伝えようとしています。

あなたは大失敗しました。あなたの文法にバグがあります。いくつかのプロダクションのルールを作成しようとしましたが、それを認識させなかったので、追加しても意味がありませんでした。

か、その辺...

たぶんあなたが必要です:

program
    : definitions statements
    ;

または、関数も定義として許可する必要があるかもしれません。そうすれば、FOR ステートメントは関数の本体の一部になります。

于 2013-01-07T19:09:00.497 に答える
0

あなたの修正された文法について私のLLオラクルに尋ねます:

Out of 15 non-terminals, 14 are reachable, 1 are unreachable:
'declarations'
Circular symbols:
definitions
definitions

循環シンボルに関する不満は、「定義」がそれ自体を導出できることを意味します。たとえば、'definitions' は 'definitions definition' を生成できますが、'definitions' は null 許容であるため、'definitions' はそれ自体を生成できます。kinduva 無限ループのパーサー ジェネレーターは、適切な方法で処理することを気にしません。別の見方をすると、'definitions' を NULL 許容シンボルのリストとして定義したので、いくつのイプシロンを一致させたいですか? 無限はどうですか?:-)

これは、文法に問題があっても何らかのパーサーを生成しようとする yacc/bison スタイルの欠点です。自分が何をしているのかを正確に知っている場合は非常に便利ですが、そうでない場合は非常に混乱します。

しかし、非常に役に立たない (しかしガムコンパイル可能!) パーサーを与えている文法の循環性について何をすべきかという狭義のポイントに。「定義」をnull可能にするが「定義」は許可しないのはどうですか? IOW:

definitions : | definitions definition ;
definition : declaration ;

null 可能性の上に null 可能性を積み重ねないようにしてください。したがって、後で次のように変更すると:

definition : declarations ;

「宣言」を null 可能にしないでください (これは、「定義」が null 可能であることによって既に処理されています)。代わりに、次のように変更します。

declarations : declaration | declarations declaration ;

これにより、差し迫った問題を乗り越えて、いくつかの新しい問題に取り掛かることができます:-)

于 2013-02-05T08:18:35.800 に答える