From f19e68c714c20a6bd0d40efa876fd3a3ba565fed Mon Sep 17 00:00:00 2001 From: "John Hodge (bugs)" Date: Fri, 28 Nov 2014 21:46:17 +0800 Subject: Hacking up parser --- parse/common.hpp | 5 ++ parse/expr.cpp | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parse/root.cpp | 91 +++++++++++++++++-- 3 files changed, 356 insertions(+), 8 deletions(-) create mode 100644 parse/expr.cpp (limited to 'parse') diff --git a/parse/common.hpp b/parse/common.hpp index 357944c4..34ea65a4 100644 --- a/parse/common.hpp +++ b/parse/common.hpp @@ -5,9 +5,14 @@ if((tok = lex.getToken()).type() != exp) \ throw ParseError::Unexpected(tok, Token(exp));\ } while(0) +#define CHECK_TOK(tok, exp) do {\ + if(tok.type() != exp) \ + throw ParseError::Unexpected(tok, Token(exp));\ +} while(0) extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, bool generic_ok); extern TypeRef Parse_Type(TokenStream& lex); extern AST::Expr Parse_Expr(TokenStream& lex, bool const_only); +extern AST::Expr Parse_ExprBlock(TokenStream& lex); #endif // PARSE_COMMON_HPP_INCLUDED diff --git a/parse/expr.cpp b/parse/expr.cpp new file mode 100644 index 00000000..997b49f5 --- /dev/null +++ b/parse/expr.cpp @@ -0,0 +1,268 @@ +/* + */ +#include "preproc.hpp" +#include "parseerror.hpp" +#include "../ast/ast.hpp" +#include "common.hpp" +#include + +using AST::ExprNode; + +AST::ExprNode Parse_ExprBlockNode(TokenStream& lex); +AST::ExprNode Parse_Expr0(TokenStream& lex); +AST::ExprNode Parse_ExprBlocks(TokenStream& lex); +AST::ExprNode Parse_Expr1(TokenStream& lex); + +AST::Expr Parse_Expr(TokenStream& lex, bool const_only) +{ + return AST::Expr(Parse_Expr0(lex)); +} + +AST::Expr Parse_ExprBlock(TokenStream& lex) +{ + return AST::Expr(Parse_ExprBlockNode(lex)); +} + +ExprNode Parse_ExprBlockNode(TokenStream& lex) +{ + ::std::vector nodes; + Token tok; + bool trailing_value = false; + GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); + while( (tok = lex.getToken()).type() != TOK_BRACE_CLOSE ) + { + // 1. Handle 'let' + // 2. Handle new blocks + // 3. Handle a sequence of expressions broken by ';' + switch(tok.type()) + { + case TOK_BRACE_OPEN: + lex.putback(tok); + nodes.push_back(Parse_ExprBlockNode(lex)); + trailing_value = true; + break; + case TOK_RWORD_LET: + //ret.append(); + throw ParseError::Todo("block let"); + GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + trailing_value = false; + break; + case TOK_RWORD_LOOP: + throw ParseError::Todo("loop"); + break; + case TOK_RWORD_FOR: + throw ParseError::Todo("for"); + break; + case TOK_RWORD_WHILE: + throw ParseError::Todo("while"); + break; + default: + lex.putback(tok); + nodes.push_back(Parse_Expr0(lex)); + tok = lex.getToken(); + if(tok.type() != TOK_SEMICOLON) + { + if(tok.type() != TOK_BRACE_CLOSE) + throw ParseError::Unexpected(tok, Token(TOK_SEMICOLON)); + else + lex.putback(tok); + trailing_value = true; + } + else{ + trailing_value = false; + } + break; + } + } + if( trailing_value == false ) + { + nodes.push_back(ExprNode()); + } + return AST::ExprNode(ExprNode::TagBlock(), nodes); +} + +// 0: Assign +AST::ExprNode Parse_Expr0(TokenStream& lex) +{ + AST::ExprNode rv = Parse_ExprBlocks(lex); + Token tok = lex.getToken(); + if( tok.type() == TOK_EQUAL ) + { + ExprNode val = Parse_Expr1(lex); + rv = ExprNode(ExprNode::TagAssign(), rv, val); + } + else + { + lex.putback(tok); + } + return rv; +} + +// 0.5: Blocks +AST::ExprNode Parse_ExprBlocks(TokenStream& lex) +{ + Token tok = lex.getToken(); + switch( tok.type() ) + { + case TOK_RWORD_MATCH: + throw ParseError::Todo("match"); + break; + case TOK_RWORD_IF: + throw ParseError::Todo("if"); + break; + default: + lex.putback(tok); + return Parse_Expr1(lex); + } +} + + +#define LEFTASSOC(cur, next, cases) \ +AST::ExprNode next(TokenStream& lex); \ +AST::ExprNode cur(TokenStream& lex) \ +{ \ + ::std::cout << ">>" << #cur << ::std::endl; \ + AST::ExprNode rv = next(lex); \ + while(true) \ + { \ + Token tok; \ + switch((tok = lex.getToken()).type()) \ + { \ + cases \ + default: \ + ::std::cout << "<<" << #cur << ::std::endl; \ + lex.putback(tok); \ + return rv; \ + } \ + } \ +} +// 1: Bool OR +LEFTASSOC(Parse_Expr1, Parse_Expr2, + case TOK_DOUBLE_PIPE: + throw ParseError::Todo("expr - boolean OR"); +) +// 2: Bool AND +LEFTASSOC(Parse_Expr2, Parse_Expr3, + case TOK_DOUBLE_AMP: + throw ParseError::Todo("expr - boolean AND"); +) +// 3: (In)Equality +LEFTASSOC(Parse_Expr3, Parse_Expr4, + case TOK_DOUBLE_EQUAL: + throw ParseError::Todo("expr - equal"); + case TOK_EXLAM_EQUAL: + throw ParseError::Todo("expr - not equal"); +) +// 4: Comparisons +LEFTASSOC(Parse_Expr4, Parse_Expr5, + case TOK_LT: + throw ParseError::Todo("expr - less than"); + case TOK_GT: + throw ParseError::Todo("expr - greater than"); + case TOK_LTE: + throw ParseError::Todo("expr - less than or equal"); + case TOK_GTE: + throw ParseError::Todo("expr - greater than or equal"); +) +// 5: Bit OR +LEFTASSOC(Parse_Expr5, Parse_Expr6, + case TOK_PIPE: + throw ParseError::Todo("expr - bitwise OR"); +) +// 6: Bit XOR +LEFTASSOC(Parse_Expr6, Parse_Expr7, + case TOK_CARET: + throw ParseError::Todo("expr - bitwise XOR"); +) +// 7: Bit AND +LEFTASSOC(Parse_Expr7, Parse_Expr8, + case TOK_AMP: + throw ParseError::Todo("expr - bitwise AND"); +) +// 8: Bit Shifts +LEFTASSOC(Parse_Expr8, Parse_Expr9, + case TOK_DOUBLE_LT: + throw ParseError::Todo("expr - shift left"); + case TOK_DOUBLE_GT: + throw ParseError::Todo("expr - shift right"); +) +// 9: Add / Subtract +LEFTASSOC(Parse_Expr9, Parse_Expr10, + case TOK_PLUS: + throw ParseError::Todo("expr - add"); + case TOK_DASH: + throw ParseError::Todo("expr - sub"); +) +// 10: Cast +LEFTASSOC(Parse_Expr10, Parse_Expr11, + case TOK_RWORD_AS: + throw ParseError::Todo("expr - cast"); +) +// 11: Times / Divide / Modulo +LEFTASSOC(Parse_Expr11, Parse_Expr12, + case TOK_STAR: + throw ParseError::Todo("expr - multiply"); + case TOK_SLASH: + throw ParseError::Todo("expr - divide"); + case TOK_PERCENT: + throw ParseError::Todo("expr - modulo"); +) +// 12: Unaries +AST::ExprNode Parse_ExprVal(TokenStream& lex); +AST::ExprNode Parse_Expr12(TokenStream& lex) +{ + Token tok; + switch((tok = lex.getToken()).type()) + { + case TOK_DASH: + throw ParseError::Todo("expr - negate"); + case TOK_EXLAM: + throw ParseError::Todo("expr - logical negate"); + case TOK_STAR: + throw ParseError::Todo("expr - dereference"); + case TOK_RWORD_BOX: + throw ParseError::Todo("expr - box"); + case TOK_AMP: + throw ParseError::Todo("expr - borrow"); + default: + lex.putback(tok); + return Parse_ExprVal(lex); + } +} + +AST::ExprNode Parse_ExprVal(TokenStream& lex) +{ + Token tok; + AST::Path path; + switch((tok = lex.getToken()).type()) + { + case TOK_IDENT: + // Get path + lex.putback(tok); + path = Parse_Path(lex, false, true); + if(0) + case TOK_DOUBLE_COLON: + path = Parse_Path(lex, true, true); + switch( (tok = lex.getToken()).type() ) + { + case TOK_BRACE_OPEN: + // Structure literal + throw ParseError::Todo("Structure literal"); + break; + case TOK_PAREN_OPEN: + // Function call + throw ParseError::Todo("Function call"); + break; + default: + // Value + lex.putback(tok); + throw ParseError::Todo("Variable/Constant"); + } + case TOK_INTEGER: + return ExprNode(ExprNode::TagInteger(), tok.intval(), tok.datatype()); + case TOK_FLOAT: + throw ParseError::Todo("Float"); + default: + throw ParseError::Unexpected(tok); + } +} diff --git a/parse/root.cpp b/parse/root.cpp index 789d30b0..f78e9c1f 100644 --- a/parse/root.cpp +++ b/parse/root.cpp @@ -225,8 +225,7 @@ AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex) is_mut = true; tok = lex.getToken(); } - if(tok.type() != TOK_IDENT) - throw ParseError::Unexpected(tok, Token(TOK_IDENT)); + CHECK_TOK(tok, TOK_IDENT); ::std::string name = tok.str(); GET_CHECK_TOK(tok, lex, TOK_COLON); @@ -240,15 +239,64 @@ AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex) mod.add_global(is_public, is_mut, name, type, val); break; } - case TOK_RWORD_FN: - throw ParseError::Todo("modroot fn"); + case TOK_RWORD_FN: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + tok = lex.getToken(); + AST::TypeParams params; + if( tok.type() == TOK_LT ) + { + params = Parse_TypeParams(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + tok = lex.getToken(); + if(tok.type() == TOK_RWORD_WHERE) + { + Parse_TypeConds(lex, params); + tok = lex.getToken(); + } + } + CHECK_TOK(tok, TOK_PAREN_OPEN); + tok = lex.getToken(); + ::std::vector args; + if( tok.type() != TOK_PAREN_CLOSE ) + { + // Argument list + lex.putback(tok); + do { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_COLON); + TypeRef type = Parse_Type(lex); + args.push_back( ::std::make_pair(name, type) ); + tok = lex.getToken(); + } while( tok.type() == TOK_COMMA ); + CHECK_TOK(tok, TOK_PAREN_CLOSE); + } + + TypeRef ret_type; + tok = lex.getToken(); + if( tok.type() == TOK_THINARROW ) + { + // Return type + ret_type = Parse_Type(lex); + } + else + { + lex.putback(tok); + } + + AST::Expr code = Parse_ExprBlock(lex); + + mod.add_function(is_public, name, params, ret_type, args, code); + break; } case TOK_RWORD_STRUCT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); tok = lex.getToken(); + AST::TypeParams params; if( tok.type() == TOK_LT ) { - AST::TypeParams params = Parse_TypeParams(lex); + params = Parse_TypeParams(lex); GET_CHECK_TOK(tok, lex, TOK_GT); tok = lex.getToken(); if(tok.type() == TOK_RWORD_WHERE) @@ -259,6 +307,20 @@ AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex) } if(tok.type() == TOK_PAREN_OPEN) { + TypeRef inner = Parse_Type(lex); + tok = lex.getToken(); + if(tok.type() != TOK_PAREN_CLOSE) + { + ::std::vector refs; + refs.push_back(inner); + while( (tok = lex.getToken()).type() == TOK_COMMA ) + { + refs.push_back( Parse_Type(lex) ); + } + if( tok.type() != TOK_PAREN_CLOSE ) + throw ParseError::Unexpected(tok, Token(TOK_PAREN_CLOSE)); + inner = TypeRef(TypeRef::TagTuple(), refs); + } throw ParseError::Todo("tuple struct"); } else if(tok.type() == TOK_SEMICOLON) @@ -267,14 +329,27 @@ AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex) } else if(tok.type() == TOK_BRACE_OPEN) { - throw ParseError::Todo("full struct"); + ::std::vector items; + while( (tok = lex.getToken()).type() != TOK_BRACE_CLOSE ) + { + CHECK_TOK(tok, TOK_IDENT); + ::std::string name = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_COLON); + TypeRef type = Parse_Type(lex); + items.push_back( ::std::make_pair(name, type) ); + tok = lex.getToken(); + if(tok.type() == TOK_BRACE_CLOSE) + break; + if(tok.type() != TOK_COMMA) + throw ParseError::Unexpected(tok, Token(TOK_COMMA)); + } + mod.add_struct(is_public, name, params, items); } else { throw ParseError::Unexpected(tok); } - - throw ParseError::Todo("modroot struct"); } + break; } case TOK_RWORD_ENUM: throw ParseError::Todo("modroot enum"); case TOK_RWORD_IMPL: -- cgit v1.2.3