ADD: cmp operations.
parent
335189c31c
commit
217f5c2f92
|
@ -14,8 +14,13 @@ BLOCK ::= obrace INSTR* cbrace
|
||||||
DIR ::= hash ident EXPR (as ident)?
|
DIR ::= hash ident EXPR (as ident)?
|
||||||
|
|
||||||
EXPR ::=
|
EXPR ::=
|
||||||
| ADDSUB
|
| OR
|
||||||
|
|
||||||
|
OR ::= AND (or AND)*
|
||||||
|
AND ::= EQNE (and EQNE)*
|
||||||
|
|
||||||
|
EQNE ::= CMP ((eq|ne) CMP)?
|
||||||
|
CMP ::= ADDSUB ((lt|le|gt|ge) ADDSUB)?
|
||||||
|
|
||||||
ADDSUB ::= MULDIVMOD ((add|sub) MULDIVMOD)*
|
ADDSUB ::= MULDIVMOD ((add|sub) MULDIVMOD)*
|
||||||
MULDIVMOD ::= LITERAL ((mul|div|mod) LITERAL)*
|
MULDIVMOD ::= LITERAL ((mul|div|mod) LITERAL)*
|
||||||
|
@ -25,6 +30,7 @@ LITERAL ::=
|
||||||
| int
|
| int
|
||||||
| CALL
|
| CALL
|
||||||
| NS
|
| NS
|
||||||
|
| not LITERAL
|
||||||
|
|
||||||
CALL ::= ident opar ARGS cpar
|
CALL ::= ident opar ARGS cpar
|
||||||
ARGS ::= (EXPR (comma EXPR)*)?
|
ARGS ::= (EXPR (comma EXPR)*)?
|
||||||
|
|
|
@ -377,6 +377,65 @@ namespace wg
|
||||||
true));
|
true));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case NODE_BOOL: {
|
||||||
|
return llvm::ConstantInt::getBool(m_mod.context(),
|
||||||
|
node->repr() == "true");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_AND: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateAnd(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_OR: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateOr(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_NOT: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
return m_builder->CreateNot(lhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_EQ: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateICmpEQ(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_NE: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateICmpNE(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_LT: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateICmpSLT(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_LE: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateICmpSLE(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_GT: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateICmpSGT(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
|
||||||
|
case NODE_GE: {
|
||||||
|
auto lhs = compile(node->child(0));
|
||||||
|
auto rhs = compile(node->child(1));
|
||||||
|
return m_builder->CreateICmpSGE(lhs, rhs);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WG_ASSERT(false,
|
WG_ASSERT(false,
|
||||||
std::string()
|
std::string()
|
||||||
|
|
|
@ -5,11 +5,24 @@ namespace wg
|
||||||
{
|
{
|
||||||
/*explicit*/ Lexer::Lexer()
|
/*explicit*/ Lexer::Lexer()
|
||||||
{
|
{
|
||||||
|
add_keyword("true", NODE_BOOL, true);
|
||||||
|
add_keyword("false", NODE_BOOL, true);
|
||||||
add_keyword("as", NODE_AS);
|
add_keyword("as", NODE_AS);
|
||||||
add_keyword("int", NODE_TYPE, true);
|
add_keyword("int", NODE_TYPE, true);
|
||||||
add_keyword("fun", NODE_FUN);
|
add_keyword("fun", NODE_FUN);
|
||||||
add_keyword("return", NODE_RETURN);
|
add_keyword("return", NODE_RETURN);
|
||||||
add_keyword("extern", NODE_EXTERN);
|
add_keyword("extern", NODE_EXTERN);
|
||||||
|
add_keyword("and", NODE_AND);
|
||||||
|
add_keyword("or", NODE_OR);
|
||||||
|
add_keyword("not", NODE_NOT);
|
||||||
|
|
||||||
|
add_text("==", NODE_EQ);
|
||||||
|
add_text("<>", NODE_NE);
|
||||||
|
|
||||||
|
add_text("<", NODE_LT);
|
||||||
|
add_text("<=", NODE_LE);
|
||||||
|
add_text(">", NODE_GT);
|
||||||
|
add_text(">=", NODE_GE);
|
||||||
|
|
||||||
add_text(".", NODE_DOT);
|
add_text(".", NODE_DOT);
|
||||||
add_text("{", NODE_OBRACE);
|
add_text("{", NODE_OBRACE);
|
||||||
|
|
32
lib/Node.hpp
32
lib/Node.hpp
|
@ -4,21 +4,23 @@
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
#include "Loc.hpp"
|
#include "Loc.hpp"
|
||||||
|
|
||||||
#define NODE_TYPES(G) \
|
#define NODE_TYPES(G) \
|
||||||
G(NODE_PROG), \
|
G(NODE_PROG), \
|
||||||
G(NODE_IDENT), \
|
G(NODE_IDENT), \
|
||||||
G(NODE_HASH), \
|
G(NODE_HASH), \
|
||||||
G(NODE_DIR), \
|
G(NODE_DIR), \
|
||||||
G(NODE_INT), \
|
G(NODE_INT), \
|
||||||
G(NODE_ADD), G(NODE_SUB), \
|
G(NODE_ADD), G(NODE_SUB), \
|
||||||
G(NODE_MUL),G(NODE_DIV), \
|
G(NODE_MUL),G(NODE_DIV), \
|
||||||
G(NODE_MOD), G(NODE_OPAR), G(NODE_CPAR), \
|
G(NODE_MOD), G(NODE_OPAR), G(NODE_CPAR), \
|
||||||
G(NODE_SEMICOLON), G(NODE_COMMA), G(NODE_CALL), \
|
G(NODE_SEMICOLON), G(NODE_COMMA), G(NODE_CALL), \
|
||||||
G(NODE_ARGS), G(NODE_TYPE), G(NODE_RETURN), \
|
G(NODE_ARGS), G(NODE_TYPE), G(NODE_RETURN), \
|
||||||
G(NODE_FUN), G(NODE_PARAMS), G(NODE_BLOCK), \
|
G(NODE_FUN), G(NODE_PARAMS), G(NODE_BLOCK), \
|
||||||
G(NODE_OBRACE), G(NODE_CBRACE), G(NODE_FUNDECL), \
|
G(NODE_OBRACE), G(NODE_CBRACE), G(NODE_FUNDECL), \
|
||||||
G(NODE_EXTERN), G(NODE_RET), G(NODE_DOT), G(NODE_NS), \
|
G(NODE_EXTERN), G(NODE_RET), G(NODE_DOT), G(NODE_NS), \
|
||||||
G(NODE_AS)
|
G(NODE_AS), G(NODE_BOOL), G(NODE_AND), G(NODE_OR), \
|
||||||
|
G(NODE_NOT), G(NODE_EQ), G(NODE_NE), G(NODE_LT), G(NODE_GT), \
|
||||||
|
G(NODE_LE), G(NODE_GE)
|
||||||
|
|
||||||
namespace wg
|
namespace wg
|
||||||
{
|
{
|
||||||
|
|
|
@ -243,7 +243,71 @@ namespace wg
|
||||||
|
|
||||||
std::shared_ptr<Node> Parser::parse_expr()
|
std::shared_ptr<Node> Parser::parse_expr()
|
||||||
{
|
{
|
||||||
return parse_addsub();
|
return parse_or();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_or()
|
||||||
|
{
|
||||||
|
auto lhs = parse_and();
|
||||||
|
|
||||||
|
while (type_is(NODE_OR))
|
||||||
|
{
|
||||||
|
auto node = consume();
|
||||||
|
node->add_child(lhs);
|
||||||
|
node->add_child(parse_and());
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_and()
|
||||||
|
{
|
||||||
|
auto lhs = parse_eqne();
|
||||||
|
|
||||||
|
while (type_is(NODE_AND))
|
||||||
|
{
|
||||||
|
auto node = consume();
|
||||||
|
node->add_child(lhs);
|
||||||
|
node->add_child(parse_eqne());
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_eqne()
|
||||||
|
{
|
||||||
|
auto lhs = parse_cmp();
|
||||||
|
|
||||||
|
if (type_is(NODE_EQ)
|
||||||
|
|| type_is(NODE_NE))
|
||||||
|
{
|
||||||
|
auto node = consume();
|
||||||
|
node->add_child(lhs);
|
||||||
|
node->add_child(parse_cmp());
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Node> Parser::parse_cmp()
|
||||||
|
{
|
||||||
|
auto lhs = parse_addsub();
|
||||||
|
|
||||||
|
if (type_is(NODE_LT)
|
||||||
|
|| type_is(NODE_LE)
|
||||||
|
|| type_is(NODE_GT)
|
||||||
|
|| type_is(NODE_GE))
|
||||||
|
{
|
||||||
|
auto node = consume();
|
||||||
|
node->add_child(lhs);
|
||||||
|
node->add_child(parse_addsub());
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Node> Parser::parse_addsub()
|
std::shared_ptr<Node> Parser::parse_addsub()
|
||||||
|
@ -293,7 +357,15 @@ namespace wg
|
||||||
return parse_ns();
|
return parse_ns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type_is(NODE_NOT))
|
||||||
|
{
|
||||||
|
auto node = consume();
|
||||||
|
node->add_child(parse_literal());
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
if (type_is(NODE_INT)
|
if (type_is(NODE_INT)
|
||||||
|
|| type_is(NODE_BOOL)
|
||||||
|| type_is(NODE_IDENT))
|
|| type_is(NODE_IDENT))
|
||||||
{
|
{
|
||||||
return consume();
|
return consume();
|
||||||
|
|
|
@ -38,6 +38,11 @@ namespace wg
|
||||||
std::shared_ptr<Node> parse_dir();
|
std::shared_ptr<Node> parse_dir();
|
||||||
|
|
||||||
std::shared_ptr<Node> parse_expr();
|
std::shared_ptr<Node> parse_expr();
|
||||||
|
std::shared_ptr<Node> parse_or();
|
||||||
|
std::shared_ptr<Node> parse_and();
|
||||||
|
|
||||||
|
std::shared_ptr<Node> parse_eqne();
|
||||||
|
std::shared_ptr<Node> parse_cmp();
|
||||||
|
|
||||||
std::shared_ptr<Node> parse_addsub();
|
std::shared_ptr<Node> parse_addsub();
|
||||||
std::shared_ptr<Node> parse_muldivmod();
|
std::shared_ptr<Node> parse_muldivmod();
|
||||||
|
|
|
@ -84,3 +84,30 @@ TEST_CASE_METHOD(LexerTest, "Lexer_as")
|
||||||
test_next(lex, "AS");
|
test_next(lex, "AS");
|
||||||
test_end(lex);
|
test_end(lex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(LexerTest, "Lexer_bool")
|
||||||
|
{
|
||||||
|
wg::Lexer lex;
|
||||||
|
lex.scan(" true and false or not afalse truea ");
|
||||||
|
test_next(lex, "BOOL[true]");
|
||||||
|
test_next(lex, "AND");
|
||||||
|
test_next(lex, "BOOL[false]");
|
||||||
|
test_next(lex, "OR");
|
||||||
|
test_next(lex, "NOT");
|
||||||
|
test_next(lex, "IDENT[afalse]");
|
||||||
|
test_next(lex, "IDENT[truea]");
|
||||||
|
test_end(lex);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(LexerTest, "Lexer_cmp")
|
||||||
|
{
|
||||||
|
wg::Lexer lex;
|
||||||
|
lex.scan(" == <> < <= > >= ");
|
||||||
|
test_next(lex, "EQ");
|
||||||
|
test_next(lex, "NE");
|
||||||
|
test_next(lex, "LT");
|
||||||
|
test_next(lex, "LE");
|
||||||
|
test_next(lex, "GT");
|
||||||
|
test_next(lex, "GE");
|
||||||
|
test_end(lex);
|
||||||
|
}
|
||||||
|
|
|
@ -103,3 +103,18 @@ TEST_CASE_METHOD(ParserTest, "Parser_namespace")
|
||||||
"CALL(IDENT[d],ARGS)))",
|
"CALL(IDENT[d],ARGS)))",
|
||||||
" a.b.c.d(); ");
|
" a.b.c.d(); ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ParserTest, "Parser_bool")
|
||||||
|
{
|
||||||
|
test_parse("PROG(OR(AND(NOT(BOOL[true]),BOOL[false]),BOOL[true]))",
|
||||||
|
" not true and false or true; ");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ParserTest, "Parser_comparisons")
|
||||||
|
{
|
||||||
|
test_parse("PROG(AND(EQ(INT[7],INT[3]),LT(INT[3],INT[7])))",
|
||||||
|
" 7 == 3 and 3 < 7; ");
|
||||||
|
|
||||||
|
test_parse("PROG(OR(NE(INT[7],INT[3]),GE(INT[3],INT[7])))",
|
||||||
|
" 7 <> 3 or 3 >= 7; ");
|
||||||
|
}
|
||||||
|
|
Reference in New Issue