/* =============================================================================
//
// This file is part of the qlow compiler.
//
// Copyright (C) 2014-2015 Nicolas Winkler
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// ===========================================================================*/
%{
#include
#include
#include
#include
#include "Ast.h"
using namespace qlow::ast;
extern int qlow_parser_lex();
int qlow_parser_error(const char*)
{
throw "syntax error";
}
using ClassList = std::vector>;
std::unique_ptr parsedClasses;
%}
%define api.prefix {qlow_parser_}
/*
%skeleton "lalr1.cc" // generate C++ parser
//%define api.namespace {uetli::parser}
//%define api.value.type {struct semantic_type}
//%define parser_class_name {Parser}
//%name-prefix "uetli_parser_"
*/
%union {
//using qlow::ast::Class;
std::vector>* classes;
qlow::ast::Class* classDefinition;
qlow::ast::FeatureDeclaration* featureDeclaration;
std::vector>* featureList;
std::vector>* argumentList;
std::vector>* statements;
std::vector>* expressionList;
qlow::ast::ArgumentDeclaration* argumentDeclaration;
qlow::ast::DoEndBlock* doEndBlock;
qlow::ast::Statement* statement;
qlow::ast::Expression* expression;
qlow::ast::Operation::Operator op;
qlow::ast::MethodDefinition* methodDefinition;
qlow::ast::FeatureCall* featureCall;
qlow::ast::AssignmentStatement* assignmentStatement;
qlow::ast::NewVariableStatement* newVariableStatement;
qlow::ast::UnaryOperation* unaryOperation;
qlow::ast::BinaryOperation* binaryOperation;
const char* cString;
std::string* string;
int token;
};
%token IDENTIFIER
%token CLASS DO END IF
%token NEW_LINE
%token COLON COMMA DOT ASSIGN OPERATOR
%token ROUND_LEFT ROUND_RIGHT
%type classes
%type classDefinition
%type featureDeclaration fieldDeclaration methodDefinition
%type featureList
%type argumentList
%type statements
%type expressionList
%type argumentDeclaration
%type doEndBlock
%type statement
%type expression operationExpression paranthesesExpression
%type operator
%type featureCall
%type assignmentStatement
%type newVariableStatement
%type unaryOperation
%type binaryOperation
%left ASTERISK SLASH
%left PLUS MINUS
%start classes
%%
/* possible newline characters
pnl:
{
}
|
pnl NEW_LINE {
};
*/
/* list of class definitions */
classes:
/* empty */ {
parsedClasses = std::make_unique();
}
|
classes classDefinition {
parsedClasses->push_back(std::move(std::unique_ptr($2)));
};
classDefinition:
CLASS IDENTIFIER featureList END {
$$ = new Class(*$2, *$3);
delete $2; delete $3; $2 = 0; $3 = 0;
};
featureList:
/* empty */ {
$$ = new std::vector>();
}
|
featureList featureDeclaration {
$$ = $1;
$$->push_back(std::move(std::unique_ptr($2)));
};
featureDeclaration:
fieldDeclaration {
$$ = $1;
}
|
methodDefinition {
$$ = $1;
};
fieldDeclaration:
IDENTIFIER COLON IDENTIFIER {
$$ = new FieldDeclaration(*$3, *$1);
delete $3; delete $1; $1 = $3 = 0;
};
methodDefinition:
IDENTIFIER COLON IDENTIFIER doEndBlock {
$$ = new MethodDefinition(*$3, *$1, std::move(std::unique_ptr($4)));
delete $3; delete $1; $1 = $3 = 0;
}
|
IDENTIFIER doEndBlock {
$$ = new MethodDefinition("", *$1, std::move(std::unique_ptr($2)));
delete $1; $1 = 0;
}
|
IDENTIFIER
ROUND_LEFT argumentList ROUND_RIGHT COLON IDENTIFIER doEndBlock {
$$ = new MethodDefinition(*$6, *$1, std::move(*$3), std::move(std::unique_ptr($7)));
delete $6; delete $1; delete $3; $1 = $6 = nullptr; $3 = nullptr;
}
|
IDENTIFIER ROUND_LEFT argumentList ROUND_RIGHT doEndBlock {
$$ = new MethodDefinition("", *$1, std::move(*$3), std::move(std::unique_ptr($5)));
delete $1; delete $3; $1 = nullptr; $3 = nullptr;
};
argumentList:
argumentDeclaration {
$$ = new std::vector>();
$$->push_back(std::unique_ptr($1));
}
|
argumentList COMMA argumentDeclaration {
$$ = $1;
$$->push_back(std::unique_ptr($3));
};
argumentDeclaration:
IDENTIFIER COLON IDENTIFIER {
$$ = new ArgumentDeclaration(*$3, *$1);
delete $3; delete $1; $1 = $3 = 0;
};
doEndBlock:
DO statements END {
$$ = new DoEndBlock(std::move(*$2));
delete $2; $2 = 0;
};
statements:
/* empty */ {
$$ = new std::vector>();
}
|
statements statement {
$$ = $1;
$$->push_back(std::move(std::unique_ptr($2)));
};
statement:
featureCall {
$$ = $1;
}
|
assignmentStatement {
$$ = $1;
}
|
newVariableStatement {
$$ = $1;
};
featureCall:
IDENTIFIER {
$$ = new FeatureCall(nullptr, *$1);
delete $1; $1 = 0;
}
|
IDENTIFIER ROUND_LEFT expressionList ROUND_RIGHT {
$$ = new FeatureCall(nullptr, *$1, std::move(*$3));
delete $1; delete $3; $1 = 0; $3 = 0;
}
|
expression DOT IDENTIFIER {
$$ = new FeatureCall(std::move(std::unique_ptr($1)), *$3);
delete $3; $3 = 0;
}
|
expression DOT IDENTIFIER ROUND_LEFT expressionList ROUND_RIGHT {
$$ = new FeatureCall(std::move(std::unique_ptr($1)), *$3,
std::move(*$5));
delete $3; $3 = 0; delete $5; $5 = 0;
};
/* list of effective arguments */
expressionList:
expression {
$$ = new std::vector>();
$$->push_back(std::move(std::unique_ptr($1)));
}
|
expressionList COMMA expression {
$$ = $1;
$$->push_back(std::move(std::unique_ptr($3)));
};
expression:
featureCall {
$$ = $1;
}
|
operationExpression {
$$ = $1;
}
|
paranthesesExpression {
$$ = $1;
};
operationExpression:
binaryOperation {
$$ = $1;
}
|
unaryOperation {
$$ = $1;
};
binaryOperation:
expression operator expression {
$$ = new BinaryOperation(std::unique_ptr($1),
std::unique_ptr($3), $2);
};
unaryOperation:
expression operator {
$$ = new UnaryOperation(std::unique_ptr($1),
UnaryOperation::SUFFIX, $2);
}
|
operator expression {
$$ = new UnaryOperation(std::unique_ptr($2),
UnaryOperation::PREFIX, $1);
};
operator:
PLUS { $$ = qlow::ast::Operation::Operator::PLUS; }
|
MINUS { $$ = qlow::ast::Operation::Operator::MINUS; }
|
ASTERISK { $$ = qlow::ast::Operation::Operator::ASTERISK; }
|
SLASH { $$ = qlow::ast::Operation::Operator::SLASH; };
paranthesesExpression:
ROUND_LEFT expression ROUND_RIGHT {
$$ = $2;
};
assignmentStatement:
IDENTIFIER ASSIGN expression {
$$ = new AssignmentStatement(std::move(*$1), std::unique_ptr($3));
delete $1; $1 = 0;
};
newVariableStatement:
IDENTIFIER COLON IDENTIFIER {
$$ = new NewVariableStatement(*$3, *$1);
delete $3; delete $1; $3 = 0; $1 = 0;
};
%%