/* ============================================================================= // // 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; }; %%