0

だから私は完全に途方に暮れています...

私のコードでは、

void Parser(FILE* file)
{
    Parser par(file);
    par.Parse();
}

メイン関数でそれを呼び出すと、 Parser(file); 取得したヘッダー ファイル (メイン ファイルに含めたもの) は次のようになります。

class Parser: public Lexer
{
public:
    Parser(FILE* file):Lexer(file);
    int Parse();
};

私が得ているエラーは次のとおりです。

p02.cpp: In function 'void Parser(FILE*)':
p02.cpp:20: error: expected ';' before 'par'
p02.cpp:21: error: 'par' was not declared in this scope
make: *** [p02.o] Error 1

私が理解していないのは、パーの前にセミコロンが必要な理由です。それはそのクラスの変数の正当な宣言ではありませんか?

Edit2:関数名をクラス名のようにパーサーに変更しても、この問題は解決しません。Parser がこのスコープで宣言されていないことを示す追加のエラーが表示されますが、Parser クラスを含むインクルード ファイルを関数の宣言のすぐ上に追加したときの様子がわかりません。

編集: マイ ファイル p02.cpp:

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

#include "p02lex.h"
#include "y.tab.h"

using namespace std;

void Parser(FILE* file)
{
    Parser par(file);
    par.Parse();
}

int main(int argc, char* argv[])
{
    char fileName[255];

    switch(argc)
    {
            case 1:
                    cout << "Enter the input file name. ";
                    cin >> fileName;
                    break;
            case 2:
                    strcpy(fileName, argv[1]);
                    break;
            default:
                    cout << "Too many arguments!\n";
                    exit(1);
    }

    FILE* file = fopen(fileName, "r");
    Parser(file);
    fclose(file);

    return 0;
}

p02lex.l:

#include "p02lex.h"

#define ID              257
...
#define PROGRAM         304

int TokenMgr(int t);
const char* getTokens(int tokenCode);

unsigned lineCount = 1, columnCount = 1;
%}

LETTER [a-z]|[A-Z]
DIGIT [0-9]

%%
// rules defined here, calling TokenMgr()
%%
int TokenMgr(int t)
{
/*      int tc = t;
    if (t == IDENTIFIER)
    {
            char s[1024];
            ToLower(s, yytext, strlen(yytext));
            tc = RW[s];
            if (tc == 0)
                    tc = t;
    }

    PrintToken(tfs, tc, line, col);
    col += yyleng; */ //JEG

    printf("Token:Code=%d Name=%10s line=%3u col=%3u Spelling=\"%s\"\n", t, getTokens(t), lineCount, columnCount, yytext);

    columnCount += yyleng;

    return /* tc */ 0; // JEG
}

Lexer::Lexer(FILE* file)
{
    yyin = file;
}

int Lexer::Scan(void)
{
    return yylex();
}

const char* getTokens(int tokenCode)
{
    switch(tokenCode)
    {
            case ID:
                    return "ID";
            ... // more cases, returning strings
            default:
                    return NULL;
    }
 }

p02lex.h:

#ifndef p02lex_h
#define p02lex_h 1
#endif

int yylex(void);

class Lexer
{
public:
    Lexer(FILE* file);

    int Scan(void);
};

p02par.h:

#ifndef p02par_h
#define p02par_h 1
#endif

using namespace std;

#ifdef __cplusplus
extern "C"
#endif

int yyparse(void);

class Parser: public Lexer
{
public:
    Parser(FILE* file):Lexer(file){}

    void Parse();

    // int Scan(void);
};

p02par.y:

#include <stdio.h>

#include "p02lex.h"
#include "p02par.h"

void yyerror(const char* m);
%}

%token PROGRAM
%token ID
%token SEMICOLON

%%
program:
    PROGRAM ID SEMICOLON
    { printf("Stuff happens!\n"); }

%%
void yyerror(const char* m)
{
    printf("%s\n", m);
}

/*Parser::Parser(FILE* file):Lexer(file)
{
}*/

int Parser::Parse()
{
    return yyparse();
}

p02make:

#LEX = flex
#YACC = yacc -d

CC = g++
OBJ = p02.o p02par.o p02lex.o

p02:    ${OBJ}
    $(CC) -o p02 ${OBJ} -ll -ly

y.tab.h p02par.cpp:     p02par.y
    yacc -d -v p02par.y
    mv y.tab.c p02par.cpp

p02lex.cpp:     p02lex.l
    lex p02lex.l
    mv lex.yy.c p02lex.cpp

p02par.o:       p02par.cpp p02par.h
    $(CC) -c -g p02par.cpp

p02.o:  p02.cpp p02lex.h p02par.h
    $(CC) -c -g p02.cpp

p02lex.o:       p02lex.cpp p02lex.h y.tab.h
    $(CC) -c -g p02lex.cpp
4

4 に答える 4

1

それはあるべきです:

Parser(File* file):Lexer(file) {}

そのコードを確認して待ってください。関数の名前を変更してください。別の名前に変更してくださいvoid Parser(FILE *f)

于 2012-11-07T06:52:08.457 に答える
1

コンストラクター宣言ではなく、コンストラクター定義にのみ初期化子リストを含めることができるため、セミコロンではなく、関数本体 (多くの場合空) が続く必要があります。名前の衝突にも少し問題があります。

void Parser(FILE* file) // here you've defined Parser as the name of a function
{
    Parser par(file); // but here you're trying to use it as the name of a class.
    par.Parse();
}

編集: 少なくとも私が手元にあるコンパイラを使用して、きれいにコンパイルされるコードを次に示します。

#include <stdio.h>

class Lexer {
    FILE *infile;
public:
    Lexer(FILE *f) : infile(f) {}
};

class Parser : public Lexer {
public:
    Parser(FILE *f) : Lexer(f) {}
    void Parse() {}
};

void do_parse(FILE *file) {
    Parser p(file);
    p.Parse();
}
于 2012-11-07T06:53:26.640 に答える
0

Parser関数にはクラスと同じ識別子があるため、修飾する必要があります。

void Parser(FILE* file)
{
    class Parser par(file);
    par.Parse();
}

関数の名前を変更することもできます。

ここにもブレースが必要です。

Parser(FILE* file):Lexer(file) {}
于 2012-11-07T06:56:57.537 に答える
-1

変化する

void Parser(FILE* file)

Parser::Parser(FILE* file)

コンストラクターには戻り値の型がありません。

于 2012-11-07T06:53:12.380 に答える