From 9a89f075b21959c69cee30b916de2e6eb09a893e Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Tue, 6 Aug 2019 13:53:46 -0700 Subject: [PATCH] Move code into folders for convenience --- 01/scanner.l | 33 +++++++++++++++ 02/ast.hpp | 110 +++++++++++++++++++++++++++++++++++++++++++++++++ 02/compile.sh | 5 +++ 02/main.cpp | 14 +++++++ 02/parser.y | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ 02/scanner.l | 34 ++++++++++++++++ 6 files changed, 307 insertions(+) create mode 100644 01/scanner.l create mode 100644 02/ast.hpp create mode 100755 02/compile.sh create mode 100644 02/main.cpp create mode 100644 02/parser.y create mode 100644 02/scanner.l diff --git a/01/scanner.l b/01/scanner.l new file mode 100644 index 0000000..b0bb329 --- /dev/null +++ b/01/scanner.l @@ -0,0 +1,33 @@ +%option noyywrap + +%{ +#include +%} + +%% + +[ \n]+ {} +\+ { std::cout << "PLUS" << std::endl; } +\* { std::cout << "TIMES" << std::endl; } +- { std::cout << "MINUS" << std::endl; } +\/ { std::cout << "DIVIDE" << std::endl; } +[0-9]+ { std::cout << "NUMBER: " << yytext << std::endl; } +defn { std::cout << "KEYWORD: defn" << std::endl; } +data { std::cout << "KEYWORD: data" << std::endl; } +case { std::cout << "KEYWORD: case" << std::endl; } +of { std::cout << "KEYWORD: of" << std::endl; } +\{ { std::cout << "OPEN CURLY" << std::endl; } +\} { std::cout << "CLOSED CURLY" << std::endl; } +\( { std::cout << "OPEN PARENTH" << std::endl; } +\) { std::cout << "CLOSE PARENTH" << std::endl; } +, { std::cout << "COMMA" << std::endl; } +-> { std::cout << "PATTERN ARROW" << std::endl; } += { std::cout << "EQUAL" << std::endl; } +[a-z][a-zA-Z]* { std::cout << "LOWERCASE IDENTIFIER: " << yytext << std::endl; } +[A-Z][a-zA-Z]* { std::cout << "UPPERCASE IDENTIFIER: " << yytext << std::endl; } + +%% + +int main() { + yylex(); +} diff --git a/02/ast.hpp b/02/ast.hpp new file mode 100644 index 0000000..e734d78 --- /dev/null +++ b/02/ast.hpp @@ -0,0 +1,110 @@ +#pragma once +#include +#include + +struct ast { + virtual ~ast() = default; +}; + +using ast_ptr = std::unique_ptr; + +struct pattern { + virtual ~pattern() = default; +}; + +using pattern_ptr = std::unique_ptr; + +struct branch { + pattern_ptr pat; + ast_ptr expr; + + branch(pattern_ptr p, ast_ptr a) + : pat(std::move(p)), expr(std::move(a)) {} +}; + +using branch_ptr = std::unique_ptr; + +struct definition { + virtual ~definition() = default; +}; + +using definition_ptr = std::unique_ptr; + +enum binop { + PLUS, + MINUS, + TIMES, + DIVIDE +}; + +struct ast_int : public ast { + int value; + + explicit ast_int(int v) + : value(v) {} +}; + +struct ast_lid : public ast { + std::string id; + + explicit ast_lid(std::string i) + : id(std::move(i)) {} +}; + +struct ast_uid : public ast { + std::string id; + + explicit ast_uid(std::string i) + : id(std::move(i)) {} +}; + +struct ast_binop : public ast { + binop op; + ast_ptr left; + ast_ptr right; + + ast_binop(binop o, ast_ptr l, ast_ptr r) + : op(o), left(std::move(l)), right(std::move(r)) {} +}; + +struct ast_app : public ast { + ast_ptr left; + ast_ptr right; + + ast_app(ast_ptr l, ast_ptr r) + : left(std::move(l)), right(std::move(r)) {} +}; + +struct ast_case : public ast { + ast_ptr of; + std::vector branches; + + ast_case(ast_ptr o, std::vector b) + : of(std::move(o)), branches(std::move(b)) {} +}; + +struct pattern_var : public pattern { + std::string var; + + pattern_var(std::string v) + : var(std::move(v)) {} +}; + +struct pattern_constr : public pattern { + std::string constr; + std::vector params; + + pattern_constr(std::string c, std::vector p) + : constr(std::move(c)), params(std::move(p)) {} +}; + +struct definition_defn : public definition { + std::string name; + std::vector params; + ast_ptr body; + + definition_defn(std::string n, std::vector p, ast_ptr b) + : name(std::move(n)), params(std::move(p)), body(std::move(b)) { + + } +}; diff --git a/02/compile.sh b/02/compile.sh new file mode 100755 index 0000000..2b2d0fe --- /dev/null +++ b/02/compile.sh @@ -0,0 +1,5 @@ +bison -o parser.cpp -d parser.y +flex -o scanner.cpp scanner.l +g++ -c -o scanner.o scanner.cpp +g++ -c -o parser.o parser.cpp +g++ main.cpp parser.o scanner.o diff --git a/02/main.cpp b/02/main.cpp new file mode 100644 index 0000000..ce3d541 --- /dev/null +++ b/02/main.cpp @@ -0,0 +1,14 @@ +#include "ast.hpp" +#include "parser.hpp" + +void yy::parser::error(const std::string& msg) { + std::cout << "An error occured: " << std::endl; +} + +extern std::vector program; + +int main() { + yy::parser parser; + parser.parse(); + std::cout << program.size() << std::endl; +} diff --git a/02/parser.y b/02/parser.y new file mode 100644 index 0000000..986c8a5 --- /dev/null +++ b/02/parser.y @@ -0,0 +1,111 @@ +%{ +#include +#include +#include "ast.hpp" +#include "parser.hpp" + +std::vector program; +extern yy::parser::symbol_type yylex(); + +%} + +%token PLUS +%token TIMES +%token MINUS +%token DIVIDE +%token INT +%token DEFN +%token DATA +%token CASE +%token OF +%token OCURLY +%token CCURLY +%token OPAREN +%token CPAREN +%token COMMA +%token ARROW +%token EQUAL +%token LID +%token UID + +%language "c++" +%define api.value.type variant +%define api.token.constructor + +%type > lowercaseParams +%type > program definitions +%type > branches +%type aAdd aMul case app appBase +%type definition +%type branch +%type pattern + +%start program + +%% + +program + : definitions { program = std::move($1); } + ; + +definitions + : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } + | definition { $$ = std::vector(); $$.push_back(std::move($1)); } + ; + +definition + : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY + { $$ = definition_ptr( + new definition_defn(std::move($2), std::move($3), std::move($6))); } + ; + +lowercaseParams + : %empty { $$ = std::vector(); } + | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } + ; + +aAdd + : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } + | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } + | aMul { $$ = std::move($1); } + ; + +aMul + : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } + | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } + | app { $$ = std::move($1); } + ; + +app + : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } + | appBase { $$ = std::move($1); } + ; + +appBase + : INT { $$ = ast_ptr(new ast_int($1)); } + | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } + | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } + | OPAREN aAdd CPAREN { $$ = std::move($2); } + | case { $$ = std::move($1); } + ; + +case + : CASE aAdd OF OCURLY branches CCURLY + { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } + ; + +branches + : branches COMMA branch { $$ = std::move($1); $1.push_back(std::move($3)); } + | branch { $$ = std::vector(); $$.push_back(std::move($1));} + ; + +branch + : pattern ARROW OCURLY aAdd CCURLY + { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } + ; + +pattern + : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } + | UID lowercaseParams + { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } + ; diff --git a/02/scanner.l b/02/scanner.l new file mode 100644 index 0000000..683deeb --- /dev/null +++ b/02/scanner.l @@ -0,0 +1,34 @@ +%option noyywrap + +%{ +#include +#include "ast.hpp" +#include "parser.hpp" + +#define YY_DECL yy::parser::symbol_type yylex() + +%} + +%% + +[ \n]+ {} +\+ { return yy::parser::make_PLUS(); } +\* { return yy::parser::make_TIMES(); } +- { return yy::parser::make_MINUS(); } +\/ { return yy::parser::make_DIVIDE(); } +[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } +defn { return yy::parser::make_DEFN(); } +data { return yy::parser::make_DATA(); } +case { return yy::parser::make_CASE(); } +of { return yy::parser::make_OF(); } +\{ { return yy::parser::make_OCURLY(); } +\} { return yy::parser::make_CCURLY(); } +\( { return yy::parser::make_OPAREN(); } +\) { return yy::parser::make_CPAREN(); } +, { return yy::parser::make_COMMA(); } +-> { return yy::parser::make_ARROW(); } += { return yy::parser::make_EQUAL(); } +[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } +[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } + +%%