从未在柠檬生成的解析器中声明自定义类成员会导致编译错误

时间:2015-02-03 14:56:49

标签: c++ c++11 lemon

我正在尝试学习如何使用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

grammar.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.

lexicon.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;
%%

的main.cpp

#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

1 个答案:

答案 0 :(得分:1)

你在AST.h中缺少大括号。

您收到的第一条错误消息表明给定的声明不允许&#34;课堂内&#34;。这是您需要的线索。它看起来不应该在一个类中,那么为什么编译器认为它是?这应该让你强烈怀疑早些时候某个地​​方有一个缺失的右括号。实际上,如果你查看你的AST.h文件,你就有了这个:

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

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

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

一般情况下,当您收到如此大量的错误消息列表时,您应该只关注第一个错误或前几个错误,并忽略其余错误。它们都可能来自同一个原因,而且你越是读到事情开始出错的地方,那么进一步的错误消息就会越少。