-2

I am trying to learn how to use the Lemon parser generator, and I built a learning project. However, when I try to compile the sources, I get some strange errors from GCC. It looks like there could be some text transcribing problem or typo, but I can't find it. I am compiling using the C++11 standard. The file "log" contains the compiler output.

I compile with

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;
}

log:

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
Michele De Pascalis
  • 932
  • 2
  • 9
  • 26
  • 1
    Thanks for providing the project. But please, instead, take the effort to type up your code and problem (ie exact error messages rather than the poetic "strange errors") on this site. That way, someone may bother to try and help you, and the solution will help other people in the future when that link dies. –  Feb 03 '15 at 14:58
  • It was in your interest that I thought it would be better to zip the whole thing, as the files are quite long. As for the title, I really don't know what would better describe the issue. Nevertheless, I'll try and come up with something right away. – Michele De Pascalis Feb 03 '15 at 15:00
  • 3
    As @Poldie said, please provide a Minimal, Complete, Verifiable Example. See the [entry in the Help Center](http://stackoverflow.com/help/mcve). Asking us to wade through a whole project is cumbersome and your link may die, so the question may become incomplete and of no help to future visitors. – DarkDust Feb 03 '15 at 15:01

1 Answers1

1

You have a missing curly brace in AST.h.

The first error message you received indicated that the given declaration wasn't allowed "in-class". This is the clue that you need. It looks like it's not supposed to be in a class, so why does the compiler think that it is? This should make you strongly suspect that somewhere earlier there is a missing closing brace. Indeed, if you look in your AST.h file, you have this:

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

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

You need to add a missing closing brace to toString.

In general, when you get a huge long list of error messages like this, you should look most closely at just the first error or the first few, and ignore the rest. They are all likely from the same cause, and the further you read past the point that things started going wrong, the less useful further error messages become.

Weeble
  • 17,058
  • 3
  • 60
  • 75
  • Actually my mind kept reading "StatementNode" instead of "IdentifierExpressionNode" in the error for no good reason. How silly... I seem to be quite prone to typo's, but after that fix the others were obvious and all is solved, thanks! – Michele De Pascalis Feb 03 '15 at 15:29