Никогда не объявленные пользовательские члены класса в парсере, генерируемом лимоном, вызывают ошибки компиляции

Я пытаюсь научиться использовать генератор анализатора 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

-2

Решение

У вас отсутствует фигурная скобка в AST.h.

Первое полученное вами сообщение об ошибке показало, что данное объявление не разрешено «в классе». Это ключ, который вам нужен. Похоже, что он не должен быть в классе, так почему компилятор считает, что это так? Это должно заставить вас сильно подозревать, что где-то раньше отсутствует закрывающая скобка. Действительно, если вы посмотрите в свой файл AST.h, у вас есть это:

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

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

Вам нужно добавить отсутствующую закрывающую скобку в toString.

В общем, когда вы получаете огромный длинный список сообщений об ошибках, подобных этому, вам следует наиболее внимательно изучить только первую или несколько первых ошибок и игнорировать остальные. Все они, вероятно, связаны с одной и той же причиной, и чем дальше вы читаете после того, как что-то пошло не так, тем менее полезными становятся сообщения об ошибках.

1

Другие решения


По вопросам рекламы [email protected]