-2

我正在尝试学习如何使用 Lemon 解析器生成器,并且我建立了一个学习项目。但是,当我尝试编译源代码时,我从 GCC 收到了一些奇怪的错误。看起来可能有一些文本转录问题或拼写错误,但我找不到。我正在使用 C++11 标准进行编译。文件“log”包含编译器输出。

我编译

flex lexicon.l
lemon grammar.y
g++ -std=c++11 -o parser lex.yy.c grammar.c main.cpp 2> log

AST.h

#ifndef AST_H
#define AST_H

#include <string>
#include <sstream>
#include <iostream>
#include <unordered_map>
using namespace std;

string itos(int i) {
    stringstream ss;
    ss << i;
    return ss.str();
}

class Identifier {
    string name;
public:
    Identifier()
    : name("") {
        cerr << "This initializer should never be called!" << endl;
    }

    Identifier(string _name)
    : name(_name) {
    }
    string getName() {
        return name;
    }
};

unordered_map<string, Identifier> identifiers;

class ASTNode {
public:
    virtual string toString() = 0;
};

class StatementNode: public ASTNode {
public:
    virtual string toString() = 0;
};

class AssignmentNode: public StatementNode {
    Identifier *id;
    int newValue;
public:
    AssignmentNode(Identifier *_id, int _newValue)
    : id(_id),
      newValue(_newValue) {
    }

    string toString() {
        return id->getName() + " is now " + itos(newValue);
    }
};

class ExpressionNode: public StatementNode {
public:
    virtual string toString() = 0;
};

class ValueExpressionNode: public ExpressionNode {
    int value;
public:
    ValueExpressionNode(int _value)
    : value(_value) {
    }

    string toString() {
        return string("value: ") + itos(value);
    }
};

class IdentifierExpressionNode: public ExpressionNode {
    Identifier *id;
public:
    IdentifierExpressionNode(Identifier *_id)
    : id(_id) {
    }

    string toString() {
        return string("id : ") + id->getName();
};

class PlusExpressionNode: public ExpressionNode {
    ExpressionNode *lexp;
    ExpressionNode *rexp;
public:
    PlusExpressionNode(ExpressionNode *_lexp, ExpressionNode *_rexp)
    : lexp(_lexp),
      rexp(_rexp) {
    }

    string toString() {
        return string("(") + lexp->toString() + " + " + rexp->toString() + ")";
    }
};

class MinusExpressionNode: public ExpressionNode {
    ExpressionNode *lexp;
    ExpressionNode *rexp;
public:
    MinusExpressionNode(ExpressionNode *_lexp, ExpressionNode *_rexp)
    : lexp(_lexp),
      rexp(_rexp) {
    }

    string toString() {
        return string("(") + lexp->toString() + " - " + rexp->toString() + ")";
    }
};

class TimesExpressionNode: public ExpressionNode {
    ExpressionNode *lexp;
    ExpressionNode *rexp;
public:
    TimesExpressionNode(ExpressionNode *_lexp, ExpressionNode *_rexp)
    : lexp(_lexp),
      rexp(_rexp) {
    }

    string toString() {
        return string("(") + lexp->toString() + " * " + rexp->toString() + ")";
    }
};

class DividedByExpressionNode: public ExpressionNode {
    ExpressionNode *lexp;
    ExpressionNode *rexp;
public:
    DividedByExpressionNode(ExpressionNode *_lexp, ExpressionNode *_rexp)
    : lexp(_lexp),
      rexp(_rexp) {
    }

    string toString() {
        return string("(") + lexp->toString() + " / " + rexp->toString() + ")";
    }
};

#endif

语法.y:

%include {
#include <vector>
#include <iostream>
#include <cassert>
#include <sstream>
#include "AST.h"

int atoi (char * a) {
    std::stringstream ss;
    ss << a;
    int i;
    ss >> i;
    return i;
}

Identifier* idForName(string name) {
    if (identifiers.find(name) == identifiers.end()) {
        identifiers[name] = Identifier(name);
    }
    return &(identifiers.at(name));
}
}

%token_type {char *}
%extra_argument {std::vector<StatementNode*>* statements}

start ::= statements.

statements ::= statement(stmt).
{
    statements->push_back(stmt);
}

statements ::= statements NEWLINE statement(stmt).
{
    statements->push_back(stmt);
}

%type statement {StatementNode*}

statement(stmt) ::= assignment(asgn).
{
    stmt = asgn;
}

%type assignment {AssignmentNode*}

assignment(asgn) ::= IDENTIFIER(id) EQUALS NUMBER(num).
{

    asgn = new AssignmentNode(idForName(id)), atoi(num));
}

statement(stmt) ::= expression(expr).
{
    stmt = expr;
}

%type expression {ExpressionNode*}

expression(expr) ::= NUMBER(num).
{
    expr = new ValueExpressionNode(atoi(num));
}

expression(expr) ::= IDENTIFIER(id).
{
    expr = IdentifierExpression(idForName(id));
}

expression(expr) ::= LROUNDPAREN expression(pexpr) RROUNDPAREN.
{
    expr = pexpr;
}

expression(expr) ::= expression(lexp) PLUS expression(rexp).
{
    expr = new PlusExpressionNode(lexp, rexp);
}

expression(expr) ::= expression(lexp) MINUS expression(rexp).
{
    expr = new MinusExpressionNode(lexp, rexp);
}

expression(expr) ::= expression(lexp) TIMES expression(rexp).
{
    expr = new TimesExpressionNode(lexp, rexp);
}

expression(expr) ::= expression(lexp) DIVIDEDBY expression(rexp).
{
    expr = new DividedByExpressionNode(lexp, rexp);
}

%left PLUS MINUS.
%left TIMES DIVIDEDBY.
%nonassoc LROUNDPAREN RROUNDPAREN.

词典.l:

%{
#include "grammar.h"
%}

%option noyywrap

%%

[A-Za-z_][A-Za-z0-9]*   return IDENTIFIER;
[0-9]+                  return NUMBER;
"="                     return EQUALS;
"+"                     return PLUS;
"-"                     return MINUS;
"*"                     return TIMES;
"/"                     return DIVIDEDBY;
"("                     return LROUNDPAREN;
")"                     return RROUNDPAREN;
\n                      return NEWLINE;
%%

主文件

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>

#include "AST.h"

using namespace std;

void* ParseAlloc(void* (*allocProc)(size_t));
void Parse(void*, int, char *, vector<StatementNode*>*);
void ParseFree(void*, void(*freeProc)(void*));

int yylex();
extern char * yytext;

int main() {
    vector<StatementNode*> statements;
    vector<char*> strpointers;
    void* parser = ParseAlloc(malloc);
    while (int lexcode = yylex()) {
        char *tmp = (char*)malloc((strlen(yytext)+1)*sizeof(char));
        strcpy(tmp, yytext);
        Parse(parser, lexcode, tmp, &statements);
        strpointers.push_back(tmp);
    }

    for (vector<StatementNode*>::iterator i = statements.begin(); i != statements.end(); i++) {
        cout << (*i)->toString() << endl;
    }

    Parse(parser, 0, NULL, &identifiers);
    ParseFree(parser, free);
    for (vector<char*>::iterator i=strpointers.begin(); i != strpointers.end(); i++) {
        free(*i);
    }

    return 0;
}

日志:

grammar.c:105:44: error: ‘constexpr’ needed for in-class initialization of static data member ‘const IdentifierExpressionNode::YYMINORTYPE IdentifierExpressionNode::yyzerominor’ of non-integral type [-fpermissive]
grammar.c:173:1: error: in-class initialization of static data member ‘const unsigned char IdentifierExpressionNode::yy_action []’ of incomplete type
grammar.c:179:1: error: in-class initialization of static data member ‘const unsigned char IdentifierExpressionNode::yy_lookahead []’ of incomplete type
grammar.c:187:1: error: in-class initialization of static data member ‘const signed char IdentifierExpressionNode::yy_shift_ofst []’ of incomplete type
grammar.c:194:1: error: in-class initialization of static data member ‘const signed char IdentifierExpressionNode::yy_reduce_ofst []’ of incomplete type
grammar.c:199:1: error: in-class initialization of static data member ‘const unsigned char IdentifierExpressionNode::yy_default []’ of incomplete type
grammar.c:257:28: error: ‘constexpr’ needed for in-class initialization of static data member ‘FILE* IdentifierExpressionNode::yyTraceFILE’ of non-integral type [-fpermissive]
grammar.c:258:30: error: ‘constexpr’ needed for in-class initialization of static data member ‘char* IdentifierExpressionNode::yyTracePrompt’ of non-integral type [-fpermissive]
grammar.c:296:1: error: in-class initialization of static data member ‘const char* const IdentifierExpressionNode::yyTokenName []’ of incomplete type
grammar.c:316:1: error: in-class initialization of static data member ‘const char* const IdentifierExpressionNode::yyRuleName []’ of incomplete type
grammar.c:642:1: error: in-class initialization of static data member ‘const IdentifierExpressionNode::<anonymous struct> IdentifierExpressionNode::yyRuleInfo []’ of incomplete type
grammar.c:842:13: error: ‘static void IdentifierExpressionNode::yy_accept(IdentifierExpressionNode::yyParser*)’ cannot be overloaded
grammar.c:644:13: error: with ‘static void IdentifierExpressionNode::yy_accept(IdentifierExpressionNode::yyParser*)’
grammar.c:1025:1: error: expected ‘}’ at end of input
grammar.y: In static member function ‘static void IdentifierExpressionNode::yy_reduce(IdentifierExpressionNode::yyParser*, int)’:
grammar.y:51:69: error: cannot call member function ‘Identifier* IdentifierExpressionNode::idForName(std::string)’ without object
grammar.y:51:96: error: cannot call member function ‘int IdentifierExpressionNode::atoi(char*)’ without object
grammar.y:51:97: error: expected ‘;’ before ‘)’ token
grammar.y:63:68: error: cannot call member function ‘int IdentifierExpressionNode::atoi(char*)’ without object
grammar.y:68:70: error: cannot call member function ‘Identifier* IdentifierExpressionNode::idForName(std::string)’ without object
grammar.y:68:71: error: ‘IdentifierExpression’ was not declared in this scope
grammar.c: At global scope:
grammar.c:1025:1: error: expected unqualified-id at end of input
main.cpp:9:7: error: expected nested-name-specifier before ‘namespace’
main.cpp:9:7: error: expected unqualified-id before ‘namespace’
main.cpp:9:7: error: expected ‘;’ before ‘namespace’
main.cpp:9:7: error: expected unqualified-id before ‘namespace’
main.cpp:16:15: error: storage class specified for ‘yytext’
main.cpp:40:1: error: expected ‘}’ at end of input
main.cpp: In member function ‘int IdentifierExpressionNode::main()’:
main.cpp:33:37: error: no matching function for call to ‘IdentifierExpressionNode::Parse(void*&, int, NULL, std::unordered_map<std::basic_string<char>, Identifier>*)’
main.cpp:33:37: note: candidate is:
main.cpp:12:6: note: void IdentifierExpressionNode::Parse(void*, int, char*, std::vector<StatementNode*>*)
main.cpp:12:6: note:   no known conversion for argument 4 from ‘std::unordered_map<std::basic_string<char>, Identifier>*’ to ‘std::vector<StatementNode*>*’
main.cpp: At global scope:
main.cpp:40:1: error: expected unqualified-id at end of input
4

1 回答 1

1

您在 AST.h 中缺少一个花括号。

您收到的第一条错误消息表明给定的声明不允许“在课堂上”。这是您需要的线索。看起来它不应该在一个类中,那么为什么编译器会认为它是呢?这应该使您强烈怀疑在更早的地方缺少右括号。事实上,如果你查看你的 AST.h 文件,你有这个:

class IdentifierExpressionNode: public ExpressionNode {
    Identifier *id;
public:
    IdentifierExpressionNode(Identifier *_id)
    : id(_id) {
    }

    string toString() {
        return string("id : ") + id->getName();
};

您需要向 toString 添加缺少的右大括号。

通常,当您收到一长串类似这样的错误消息时,您应该最仔细地查看第一个错误或前几个错误,而忽略其余的。它们都可能出于相同的原因,并且您越深入地了解事情开始出错的点,进一步的错误消息就越没用。

于 2015-02-03T15:11:40.007 回答