1

パーサーを実行するたびに、「<> 付近の 1 行目の構文エラー」が表示されます (サブルーチン yyerror(char *s) があるため)。バイソンのルールに何か問題があるためだと思います。

解析したいファイル (c17.isc)。

*c17 iscas example (to test conversion program only)
*---------------------------------------------------
*
*
*  total number of lines in the netlist ..............    17
*  simplistically reduced equivalent fault set size =     22
*        lines from primary input  gates .......     5
*        lines from primary output gates .......     2
*        lines from interior gate outputs ......     4
*        lines from **     3 ** fanout stems ...     6
*
*        avg_fanin  =  2.00,     max_fanin  =  2
*        avg_fanout =  2.00,     max_fanout =  2
*
*
*
*
*
    1     1gat inpt    1   0      >sa1
    2     2gat inpt    1   0      >sa1
    3     3gat inpt    2   0 >sa0 >sa1
    8     8fan from     3gat      >sa1
    9     9fan from     3gat      >sa1
    6     6gat inpt    1   0      >sa1
    7     7gat inpt    1   0      >sa1
   10    10gat nand    1   2      >sa1
     1     8
   11    11gat nand    2   2 >sa0 >sa1
     9     6
   14    14fan from    11gat      >sa1
   15    15fan from    11gat      >sa1
   16    16gat nand    2   2 >sa0 >sa1
     2    14
   20    20fan from    16gat      >sa1
   21    21fan from    16gat      >sa1
   19    19gat nand    1   2      >sa1
    15     7
   22    22gat nand    0   2 >sa0 >sa1
    10    20
   23    23gat nand    0   2 >sa0 >sa1
    21    19

私のflexファイルは次のとおりで、正しいです。私のスキャナーの仕組みについては、こちらをご覧ください。 flex ファイルの出力にエラーがあります

宣言.h

# include <stdio.h>
# include <string.h>
# include <stdlib.h>

# define INPT 1
# define NOR 2
# define NAND 3
# define NOT 4
# define XOR 5
# define AND 6
# define BUFF 7
# define FROM 8

フレックスファイルは

%{
# include "declare.h"
# include "parse.tab.h"

/*gi=1,it's input;gi=8,it's fanout;otherwise,it's gate*/
static int gi=-1;
static int inum=0;



struct{
    char *symbol;
    int val;
} symtab[]={
{"inpt", INPT},
{"nor", NOR},
{"nand", NAND},
{"not", NOT},
{"xor", XOR},
{"and", AND},
{"buff", BUFF},
{"from",FROM},
{"0",0}
};

extern FILE *yyin;

extern int yylval;
%}

%start A B C D E

DIGITS [0-9]+
BLANK [ \t\n\r\f\v\b]+
ALPHA [a-z]+

%%

"*".*\n     {BEGIN A; return(COMMENT);}

<A>{DIGITS}        {yylval=atoi(yytext); BEGIN B; return(NUM);}
<B>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN C; return(GNAME);}
<C>{DIGITS}        {yylval=atoi(yytext); BEGIN D; return(OPNUM);}
<C>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN A; return(FR);}
<D>{DIGITS}        {inum=atoi(yytext);
                    yylval=inum;
                    if(gi==1)
                    {BEGIN A;}
                    if(gi!=1)
                    {BEGIN E;}
                    return(IPNUM);
                   }

<E>{DIGITS}        {inum--;
                    yylval=atoi(yytext);
                    if(inum<0)
                    {BEGIN B; return(NUM);}
                    else
                    {BEGIN E; return(ILIST);} 
                   }


{ALPHA} {yylval=lookup(yytext);
         return(GTYPE);      
         }

">sa"[0-1] {yylval=atoi(&yytext[yyleng-1]);return(FAULT);}

{BLANK}    ;

.          ;



%%
int lookup(const char *s)
{
    int i;
    for (i = 0; symtab[i].val != 0; i++)
    {
        if (strcmp(symtab[i].symbol, s) == 0)
            break;
    }
    return(symtab[i].val);
}

bison ファイルの正しいルールは次のとおりです。

parto: 
     | parto COMMENT
     | parto parti
     ;

parti: NUM
       {...}

       GNAME
       {...}


       GTYPE
       {...}

      | parti partii 
      | parti partiii
      ;

partii:OPNUM
       {...}

       IPNUM
       {...}

       partiv

       partv
       ;

partiii: FR
        {...}

         partiv
         ;

partiv: 
      | partiv FAULT
      {...}

      ;

partv:
     | partv ILIST
     {...}

     ;
4

1 に答える 1

0

重要なコメントを回答に転送します。

コードの初版にはいくつかの問題がありました。スキャナ コードには、次のような行がありました。

<A>{DIGITS}        { yylval=atoi(yytext); return(NUM); BEGIN B; }

BEGINリターン後に表示される操作から到達不能コードに関する警告が表示されるはずです。BEGIN操作を実行する必要があります。それらは実行されていないため、開始状態に切り替えていません。

マイケルは次のようにコメントしています。

警告はありません。あなたが言うように変更し、質問のコードを編集しました。ここで、BEGIN の後に return を置きます。それでも「<�>付近の1行目の構文エラー」。

これはおそらく、十分な警告を表示して C コードをコンパイルしていないことを意味します。GCC を使用していると仮定-Wallして、初心者向けのコンパイル オプションを追加します。警告にも最適化が必要な可能性があります。

返されたトークンを (Flex スキャナーで) 印刷しましたか? で Bison 文法をコンパイルしました-DYYDEBUGか? yydebug = 1;また、プログラムでデバッグをオンにする必要がありますmain()。おそらく、期待したときにトークンを取得していない可能性があります。このコードのコンパイルはまだ試していません。トークンを追跡することは、(私の経験では) 文法を機能させるための鍵です。そうでなければ、あなたは盲目的に走っています。

FAULTもう 1 つの問題 (密接に関連) は、文法 ( bison -d grammar.ygenerate ) から etcの記号名を生成する必要があることですgrammar.tab.hCOMMENTたとえば、値 258 が割り当てられていることがわかります。ただし、スキャナーは にあるため、他の数値をまとめて返しますdeclare.h。この不一致を修正する必要があります。1 つのオプションは#include "grammar.tab.h"、スキャナーを使用することです。これは多かれ少なかれ正常です。

振り返ってみると、これはおそらく最も重要な観察結果だと思います。これが解決された後、物事は通常の C デバッグに戻ったようです。

(多くの場合、「grammar.h」をインクルードし、「grammar.tab.h」の内容が変更された場合にのみ「grammar.h」を更新するため、常にスキャナーを再コンパイルする必要はありません)。

これの重要性は、文法の実装が進化するにつれて、ルールに関連付けられたアクションが常に変化する一方で、文法で使用されるトークンのセットがかなり安定する傾向があることです。したがって、心配するほど時間がかかる場合grammar.hは、 のコピーであるファイルを作成できますが、 の内容が変更された場合にgrammar.tab.hのみ更新されます。grammar.hgrammar.tab.h

cmp -s grammar.tab.h grammar.h || cp grammar.tab.h grammar.h

これを、その文法を C ファイル (またはオブジェクト ファイル) に変換する makefile ルールに含めます。

スキャナが十分に小さく、マシンが十分に高速である場合、この改良を気にしない方が簡単かもしれません。数 MiB の RAM を搭載した 50 MHz マシンの時代には、数 GiB の RAM を搭載した 2+ GHz で複数のコアが実行されている現在よりも重要でした。

于 2013-03-21T00:03:59.713 に答える