Используя довольно простую грамматику Bison / Flex, я пытаюсь вытянуть токены / выражения в объекты C ++, чтобы сгенерировать три кода операции (т.е. внутреннее представление).Я делаю это, потому что этот конкретный парсер представляет меньшее подмножество большего парсера.Моя проблема связана с повторными выражениями / токенами.
Например:
10 + 55 будет анализироваться как 10 + 10.
10 + VARIABLLENAME будет анализироваться нормально, так как INT и VARIABLE - это разные токены.
55-HELLOWORLD / 100 снова будет анализироваться нормально, возможно потому, что по обе стороны выражения никогда не бывает двух одинаковых токенов.
55-HELLOWORLD - 100 Seg Faults out.Повторение токенов операции (т. Е. -, +, / и т. Д. Приводит к сбою синтаксического анализатора).
TLDR: при повторении типов значений (т. Е. INT, FLOAT, VARIABLE) один и тот же токен возвращается дважды.При повторении операций происходит сбой сегмента синтаксического анализатора.
Я предполагаю, что я делаю что-то, когда загружаю значения $ 1 / $ 3 в объекты класса, а затем добавляю их в стек синтаксического анализатора.Я попытался проверить адреса памяти каждой переменной + указатель, который я генерирую, и все они выглядят так, как я ожидал (т.е. я не перезаписываю один и тот же объект).Я пытался убедиться, что значения загружены как токены значения, INT |и переменный |оба корректно загружают свои соответствующие переменные в классы.
Кажется, проблема связана с выражениями операторов выражения OPERATION, когда используются два значения одного типа, выражения идентичны.Чтобы использовать более ранний пример:
10 + 55 -> выражение PLUS выражение -> $ 1 = 10, $ 3 = 10
Когда переменные загружаются как INT, обе являются ожидаемыми?
Вот мой соответствующий parser.y, а также объект, в который я пытаюсь загрузить значения.
%{
#include <cstdio>
#include <iostream>
#include "TOC/Operation.h"
#include "TOC/Value.h"
#include "TOC/Variable.h"
#include "TOC.h"
using namespace std;
extern int yylex();
extern int yyparse();
extern FILE *yyin;
void yyerror(const char *s);
%}
%code requires {
// This is required to force bison to include TOC before the preprocessing of union types and YYTYPE.
#include "TOC.h"
}
%union {
int ival;
float fval;
char *vval;
TOC * toc_T;
}
%token <ival> INT
%token <fval> FLOAT
%token <vval> VARIABLE
%token ENDL PLUS MINUS MUL DIV LPAREN RPAREN
%type <toc_T> expression1
%type <toc_T> expression
%right PLUS MINUS
%right MUL DIV
%start start
%%
start:
expressions;
expressions:
expressions expression1 ENDL
| expression1 ENDL;
expression1:
expression {
TOC* x = $1;
cout<<x->toTOCStr()<<endl;
};
expression:
expression PLUS expression {
TOC *a1 = $1;
TOC *a2 = $3;
Operation op(a1, a2, OPS::ADD);
TOC *t = &op;
$$ = t;
}
|expression MINUS expression {
TOC *a1 = $1;
TOC *a2 = $3;
Operation op(a1, a2, OPS::SUBTRACT);
TOC *t = &op;
$$ = t;
}
|expression MUL expression {
TOC *a1 = $1;
TOC *a2 = $3;
Operation op(a1, a2, OPS::MULTIPLY);
TOC *t = &op;
$$ = t;
}
|expression DIV expression {
TOC *a1 = $1;
TOC *a2 = $3;
Operation op(a1, a2, OPS::DIVIDE);
TOC *t = &op;
$$ = t;
}
|LPAREN expression RPAREN {
TOC *t = $2;
$$ = t;
}
| INT {
Value<int> v = $1;
TOC *t = &v;
$$ = t;
}
| FLOAT {
Value<float> v = $1;
TOC *t = &v;
$$ = t;
}
| VARIABLE {
char* name = $1;
Variable v(name);
TOC *t = &v;
$$ = t;
}
%%
void yyerror(const char *s) {
cout << "Parser Error: Message: " << s << endl;
exit(-1);
}
И значения, которые я пытаюсь загрузить (для большей ясности объединены в один файл).
Operation.h
enum OPS {
SUBTRACT,
ADD,
MULTIPLY,
DIVIDE,
EXPONENT
};
class Operation : public TOC{
OPS op;
public:
TOC* arg1;
TOC* arg2;
Operation(TOC* arg1_in, TOC* arg2_in, OPS operation){
tt = TOC_TYPES::OPERATION_E;
arg1 = arg1_in;
arg2 = arg2_in;
op = operation;
};
std::string toOPType(OPS e){
switch (e){
case SUBTRACT:
return "-";
case ADD:
return "+";
case MULTIPLY:
return "*";
case DIVIDE:
return "/";
case EXPONENT:
return "^";
default:
return "[Operation Error!]";
}
}
std::string toTOCStr(){
return arg1->toTOCStr() + toOPType(op) + arg2->toTOCStr();
}
};
Value.h
template <class T> class Value : public TOC {
public:
T argument;
Value(T arg){
tt = TOC_TYPES::VALUE_E;
argument = arg;
}
std::string toTOCStr(){
std::string x = std::to_string(argument);
return x;
}
};
Переменная. H
class Variable : public TOC {
public:
char *name;
Variable(char* name_in){
tt = TOC_TYPES::VARIABLE_E;
name = name_in;
}
std::string toTOCStr(){
std::string x = name;
return x;
}
};
TOC.h, если этоНужен
enum TOC_TYPES {
VARIABLE_E,
VALUE_E,
OPERATION_E
};
class TOC{
public:
TOC_TYPES tt;
virtual std::string toTOCStr() = 0;
};
Файл My Main просто загружается в файл и устанавливает yyin в его содержимое перед вызовом yyparse.Я не включил это, но могу, если нужно (это не очень интересно).
В идеале, я хотел бы загрузить все дерево анализа RD в оглавление *, которое затем можно перебрать, чтобы сгенерировать три кода операции на каждом уровне.Однако эта ошибка, повторяющая повторяющиеся токены и операции, ставит меня в тупик.