summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorJohn Hodge (bugs) <tpg@mutabah.net>2014-11-28 21:46:17 +0800
committerJohn Hodge (bugs) <tpg@mutabah.net>2014-11-28 21:46:17 +0800
commitf19e68c714c20a6bd0d40efa876fd3a3ba565fed (patch)
treecc77ef0a9ca4c92df0087ce3f0630ce1122278f1 /parse
parentd2fae3b040b20c91afff472de5154977677d06c3 (diff)
downloadmrust-f19e68c714c20a6bd0d40efa876fd3a3ba565fed.tar.gz
Hacking up parser
Diffstat (limited to 'parse')
-rw-r--r--parse/common.hpp5
-rw-r--r--parse/expr.cpp268
-rw-r--r--parse/root.cpp91
3 files changed, 356 insertions, 8 deletions
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 <iostream>
+
+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<ExprNode> 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<AST::StructItem> 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<TypeRef> 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<AST::StructItem> 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: