diff --git a/source/abstract_syntax_tree/node.cpp b/source/abstract_syntax_tree/node.cpp index 45df1a4f..96cf52c7 100644 --- a/source/abstract_syntax_tree/node.cpp +++ b/source/abstract_syntax_tree/node.cpp @@ -6,39 +6,49 @@ namespace sigma::ast { auto node_type::to_string() const->std::string { switch(type) { - case UNKNOWN: return "UNKNOWN"; + case UNKNOWN: return "UNKNOWN"; - case VARIABLE_DECLARATION: return "VARIABLE_DECLARATION"; - case FUNCTION_DECLARATION: return "FUNCTION_DECLARATION"; - case NAMESPACE_DECLARATION: return "NAMESPACE_DECLARATION"; + case VARIABLE_DECLARATION: return "VARIABLE_DECLARATION"; + case FUNCTION_DECLARATION: return "FUNCTION_DECLARATION"; + case NAMESPACE_DECLARATION: return "NAMESPACE_DECLARATION"; - case FUNCTION_CALL: return "FUNCTION_CALL"; - case RETURN: return "RETURN"; + case FUNCTION_CALL: return "FUNCTION_CALL"; + case RETURN: return "RETURN"; - case SIZEOF: return "SIZEOF"; + case SIZEOF: return "SIZEOF"; - case BRANCH: return "BRANCH"; - case CONDITIONAL_BRANCH: return "CONDITIONAL_BRANCH"; + case BRANCH: return "BRANCH"; + case CONDITIONAL_BRANCH: return "CONDITIONAL_BRANCH"; - case ARRAY_ACCESS: return "ARRAY_ACCESS"; - case VARIABLE_ACCESS: return "VARIABLE_ACCESS"; + case ARRAY_ACCESS: return "ARRAY_ACCESS"; + case VARIABLE_ACCESS: return "VARIABLE_ACCESS"; - case STORE: return "STORE"; - case LOAD: return "LOAD"; + case STORE: return "STORE"; + case LOAD: return "LOAD"; - case OPERATOR_ADD: return "OPERATOR_ADD"; - case OPERATOR_SUBTRACT: return "OPERATOR_SUBTRACT"; - case OPERATOR_MULTIPLY: return "OPERATOR_MULTIPLY"; - case OPERATOR_DIVIDE: return "OPERATOR_DIVIDE"; - case OPERATOR_MODULO: return "OPERATOR_MODULO"; + case OPERATOR_ADD: return "OPERATOR_ADD"; + case OPERATOR_SUBTRACT: return "OPERATOR_SUBTRACT"; + case OPERATOR_MULTIPLY: return "OPERATOR_MULTIPLY"; + case OPERATOR_DIVIDE: return "OPERATOR_DIVIDE"; + case OPERATOR_MODULO: return "OPERATOR_MODULO"; - case CAST: return "CAST"; + case OPERATOR_CONJUNCTION: return "OPERATOR_CONJUNCTION"; + case OPERATOR_DISJUNCTION: return "OPERATOR_DISJUNCTION"; - case NUMERICAL_LITERAL: return "NUMERICAL_LITERAL"; - case CHARACTER_LITERAL: return "CHARACTER_LITERAL"; - case STRING_LITERAL: return "STRING_LITERAL"; - case BOOL_LITERAL: return "BOOL_LITERAL"; - case NULL_LITERAL: return "NULL_LITERAL"; + case OPERATOR_GREATER_THAN: return "OPERATOR_GREATER_THAN"; + case OPERATOR_LESS_THAN: return "OPERATOR_LESS_THAN"; + case OPERATOR_GREATER_THAN_OR_EQUAL: return "OPERATOR_GREATER_THAN_OR_EQUAL"; + case OPERATOR_LESS_THAN_OR_EQUAL: return "OPERATOR_LESS_THAN_OR_EQUAL"; + case OPERATOR_EQUAL: return "OPERATOR_EQUAL"; + case OPERATOR_NOT_EQUAL: return "OPERATOR_NOT_EQUAL"; + + case CAST: return "CAST"; + + case NUMERICAL_LITERAL: return "NUMERICAL_LITERAL"; + case CHARACTER_LITERAL: return "CHARACTER_LITERAL"; + case STRING_LITERAL: return "STRING_LITERAL"; + case BOOL_LITERAL: return "BOOL_LITERAL"; + case NULL_LITERAL: return "NULL_LITERAL"; default: PANIC("to_string() not implemented for node '{}'", static_cast(type)); } diff --git a/source/abstract_syntax_tree/node.h b/source/abstract_syntax_tree/node.h index 655687d6..605cdad2 100644 --- a/source/abstract_syntax_tree/node.h +++ b/source/abstract_syntax_tree/node.h @@ -47,6 +47,16 @@ namespace sigma::ast { OPERATOR_DIVIDE, OPERATOR_MODULO, + OPERATOR_CONJUNCTION, + OPERATOR_DISJUNCTION, + + OPERATOR_GREATER_THAN, + OPERATOR_LESS_THAN, + OPERATOR_GREATER_THAN_OR_EQUAL, + OPERATOR_LESS_THAN_OR_EQUAL, + OPERATOR_EQUAL, + OPERATOR_NOT_EQUAL, + // cast // children[0] = value CAST, diff --git a/source/compiler/compiler/compiler.cpp b/source/compiler/compiler/compiler.cpp index 505b03ee..a08855ea 100644 --- a/source/compiler/compiler/compiler.cpp +++ b/source/compiler/compiler/compiler.cpp @@ -29,21 +29,16 @@ namespace sigma { // TODO: the entire frontend can be multi-threaded frontend_context frontend; - // generate tokens + // generate the AST TRY(const std::string file, utility::fs::file::load(m_description.path)); TRY(tokenizer::tokenize(file, &m_description.path, frontend)); - // TRY(parser::parse(frontend)); - - frontend.print_tokens(); - return SUCCESS; + TRY(parser::parse(frontend)); // backend // at this point we want to merge all frontend contexts into the backend context backend_context backend(frontend.syntax, m_description.target); frontend.syntax.print_ast(); - return SUCCESS; - // run analysis on the generated AST TRY(type_checker::type_check(backend)); TRY(ir_translator::translate(backend)); diff --git a/source/compiler/test/main.s b/source/compiler/test/main.s index aaacb226..c4bceddc 100644 --- a/source/compiler/test/main.s +++ b/source/compiler/test/main.s @@ -11,8 +11,9 @@ // - cleanup ir gen alignment sizes (u64 vs u32 vs u16) -i32 main() { - if(true && false || true) {} +// CHECK: +// - bool b = 100 > 200; +i32 main() { ret 0; } diff --git a/source/parser/parser.cpp b/source/parser/parser.cpp index 8a843fd8..5bedb9af 100644 --- a/source/parser/parser.cpp +++ b/source/parser/parser.cpp @@ -549,20 +549,62 @@ namespace sigma { } auto parser::parse_logical_conjunction() -> parse_result { - TRY(const handle left_node, parse_logical_disjunction()); - // TODO + TRY(handle left_node, parse_logical_disjunction()); + + while(m_tokens.get_current_token() == token_type::CONJUNCTION) { + m_tokens.next(); // prime the term + TRY(const handle right_node, parse_logical_disjunction()); + + left_node = create_binary_expression(ast::node_type::OPERATOR_CONJUNCTION, left_node, right_node); + } + return left_node; } auto parser::parse_logical_disjunction() -> parse_result { - TRY(const handle left_node, parse_comparison()); - // TODO + TRY(handle left_node, parse_comparison()); + + while(m_tokens.get_current_token() == token_type::DISJUNCTION) { + m_tokens.next(); // prime the term + TRY(const handle right_node, parse_comparison()); + + left_node = create_binary_expression(ast::node_type::OPERATOR_DISJUNCTION, left_node, right_node); + } + return left_node; } auto parser::parse_comparison() -> parse_result { - TRY(const handle left_node, parse_term()); - // TODO + TRY(handle left_node, parse_term()); + token operation = m_tokens.get_current_token(); + + while ( + operation == token_type::GREATER_THAN_OR_EQUAL || + operation == token_type::LESS_THAN_OR_EQUAL || + operation == token_type::GREATER_THAN || + operation == token_type::NOT_EQUALS || + operation == token_type::LESS_THAN || + operation == token_type::EQUALS + ) { + m_tokens.next(); // prime the comparison + + TRY(const handle right_node, parse_term()); + ast::node_type operator_type = ast::node_type::UNKNOWN; + + switch (operation) { + case token_type::GREATER_THAN_OR_EQUAL: operator_type = ast::node_type::OPERATOR_GREATER_THAN_OR_EQUAL; break; + case token_type::LESS_THAN_OR_EQUAL: operator_type = ast::node_type::OPERATOR_LESS_THAN_OR_EQUAL; break; + case token_type::GREATER_THAN: operator_type = ast::node_type::OPERATOR_GREATER_THAN; break; + case token_type::NOT_EQUALS: operator_type = ast::node_type::OPERATOR_NOT_EQUAL; break; + case token_type::LESS_THAN: operator_type = ast::node_type::OPERATOR_LESS_THAN; break; + case token_type::EQUALS: operator_type = ast::node_type::OPERATOR_EQUAL; break; + default: PANIC("unhandled term case for token '{}'", operation.to_string()); + } + + left_node = create_binary_expression(operator_type, left_node, right_node); + operation = m_tokens.get_current_token(); + } + return left_node; } diff --git a/source/tokenizer/token.cpp b/source/tokenizer/token.cpp index 7060f0f2..a14d03cc 100644 --- a/source/tokenizer/token.cpp +++ b/source/tokenizer/token.cpp @@ -39,70 +39,74 @@ namespace sigma { auto token::to_string() const -> std::string { switch (type) { - case token_type::UNKNOWN: return "UNKNOWN"; - case token_type::LEFT_PARENTHESIS: return "("; - case token_type::RIGHT_PARENTHESIS: return ")"; - case token_type::LEFT_BRACE: return "{"; - case token_type::RIGHT_BRACE: return "}"; - case token_type::LEFT_BRACKET: return "["; - case token_type::RIGHT_BRACKET: return "]"; - case token_type::COMMA: return ","; - case token_type::SEMICOLON: return ";"; - case token_type::SINGLE_QUOTE: return "'"; - case token_type::DOUBLE_QUOTE: return "\""; - case token_type::MODULO: return "%"; - case token_type::SLASH: return "/"; - case token_type::ASTERISK: return "*"; - case token_type::PLUS_SIGN: return "+"; - case token_type::MINUS_SIGN: return "-"; - case token_type::EQUALS_SIGN: return "="; - case token_type::COLON: return ":"; - case token_type::LESS_THAN: return "<"; - case token_type::GREATER_THAN: return ">"; - - case token_type::CONJUNCTION: return "&&"; - case token_type::DISJUNCTION: return "||"; - case token_type::INLINE_COMMENT: return "//"; + case token_type::UNKNOWN: return "UNKNOWN"; + case token_type::LEFT_PARENTHESIS: return "("; + case token_type::RIGHT_PARENTHESIS: return ")"; + case token_type::LEFT_BRACE: return "{"; + case token_type::RIGHT_BRACE: return "}"; + case token_type::LEFT_BRACKET: return "["; + case token_type::RIGHT_BRACKET: return "]"; + case token_type::COMMA: return ","; + case token_type::SEMICOLON: return ";"; + case token_type::SINGLE_QUOTE: return "'"; + case token_type::DOUBLE_QUOTE: return "\""; + case token_type::MODULO: return "%"; + case token_type::SLASH: return "/"; + case token_type::ASTERISK: return "*"; + case token_type::PLUS_SIGN: return "+"; + case token_type::MINUS_SIGN: return "-"; + case token_type::EQUALS_SIGN: return "="; + case token_type::COLON: return ":"; + case token_type::LESS_THAN: return "<"; + case token_type::GREATER_THAN: return ">"; + case token_type::LESS_THAN_OR_EQUAL: return "<="; + case token_type::GREATER_THAN_OR_EQUAL: return ">="; + case token_type::EQUALS: return "=="; + case token_type::NOT_EQUALS: return "!="; + + case token_type::CONJUNCTION: return "&&"; + case token_type::DISJUNCTION: return "||"; + case token_type::INLINE_COMMENT: return "//"; // default type keywords - case token_type::I8: return "I8"; - case token_type::I16: return "I16"; - case token_type::I32: return "I32"; - case token_type::I64: return "I64"; - case token_type::U8: return "U8"; - case token_type::U16: return "U16"; - case token_type::U32: return "U32"; - case token_type::U64: return "U64"; - - case token_type::BOOL: return "BOOL"; - case token_type::VOID: return "VOID"; - case token_type::CHAR: return "CHAR"; + case token_type::I8: return "I8"; + case token_type::I16: return "I16"; + case token_type::I32: return "I32"; + case token_type::I64: return "I64"; + case token_type::U8: return "U8"; + case token_type::U16: return "U16"; + case token_type::U32: return "U32"; + case token_type::U64: return "U64"; + + case token_type::BOOL: return "BOOL"; + case token_type::VOID: return "VOID"; + case token_type::CHAR: return "CHAR"; // control flow - case token_type::RET: return "RET"; - case token_type::IF: return "IF"; - case token_type::ELSE: return "ELSE"; + case token_type::RET: return "RET"; + case token_type::IF: return "IF"; + case token_type::ELSE: return "ELSE"; // other keywords - case token_type::NAMESPACE: return "NAMESPACE"; - case token_type::CAST: return "CAST"; - case token_type::SIZEOF: return "SIZEOF"; + case token_type::NAMESPACE: return "NAMESPACE"; + case token_type::CAST: return "CAST"; + case token_type::SIZEOF: return "SIZEOF"; // literals - case token_type::SIGNED_LITERAL: return "SIGNED_LITERAL"; - case token_type::UNSIGNED_LITERAL: return "UNSIGNED_LITERAL"; - case token_type::F32_LITERAL: return "F32_LITERAL"; - case token_type::F64_LITERAL: return "F64_LITERAL"; - case token_type::HEXADECIMAL_LITERAL: return "HEXADECIMAL_LITERAL"; - case token_type::BINARY_LITERAL: return "BINARY_LITERAL"; - case token_type::STRING_LITERAL: return "STRING_LITERAL"; - case token_type::CHARACTER_LITERAL: return "CHARACTER_LITERAL"; - case token_type::BOOL_LITERAL_TRUE: return "BOOL_LITERAL_TRUE"; - case token_type::BOOL_LITERAL_FALSE: return "BOOL_LITERAL_FALSE"; - case token_type::NULL_LITERAL: return "NULL"; - - case token_type::IDENTIFIER: return "IDENTIFIER"; - case token_type::END_OF_FILE: return "EOF"; + case token_type::SIGNED_LITERAL: return "SIGNED_LITERAL"; + case token_type::UNSIGNED_LITERAL: return "UNSIGNED_LITERAL"; + case token_type::F32_LITERAL: return "F32_LITERAL"; + case token_type::F64_LITERAL: return "F64_LITERAL"; + case token_type::HEXADECIMAL_LITERAL: return "HEXADECIMAL_LITERAL"; + case token_type::BINARY_LITERAL: return "BINARY_LITERAL"; + case token_type::STRING_LITERAL: return "STRING_LITERAL"; + case token_type::CHARACTER_LITERAL: return "CHARACTER_LITERAL"; + case token_type::BOOL_LITERAL_TRUE: return "BOOL_LITERAL_TRUE"; + case token_type::BOOL_LITERAL_FALSE: return "BOOL_LITERAL_FALSE"; + case token_type::NULL_LITERAL: return "null"; + + case token_type::IDENTIFIER: return "IDENTIFIER"; + case token_type::END_OF_FILE: return "EOF"; } NOT_IMPLEMENTED(); diff --git a/source/tokenizer/token.h b/source/tokenizer/token.h index 63bcdc57..0d25b957 100644 --- a/source/tokenizer/token.h +++ b/source/tokenizer/token.h @@ -9,31 +9,35 @@ namespace sigma { enum class token_type { UNKNOWN, - LEFT_PARENTHESIS, // ( - RIGHT_PARENTHESIS, // ) - LEFT_BRACE, // { - RIGHT_BRACE, // } - LEFT_BRACKET, // [ - RIGHT_BRACKET, // ] - COMMA, // , - SEMICOLON, // ; - SINGLE_QUOTE, // ' - DOUBLE_QUOTE, // " - // HASH, // # - // AMPERSAND, // & - MODULO, // % - SLASH, // / - ASTERISK, // * - PLUS_SIGN, // + - MINUS_SIGN, // + - EQUALS_SIGN, // = - COLON, // : - LESS_THAN, // < - GREATER_THAN, // > - - CONJUNCTION, // && - DISJUNCTION, // || - INLINE_COMMENT, // // + LEFT_PARENTHESIS, // ( + RIGHT_PARENTHESIS, // ) + LEFT_BRACE, // { + RIGHT_BRACE, // } + LEFT_BRACKET, // [ + RIGHT_BRACKET, // ] + COMMA, // , + SEMICOLON, // ; + SINGLE_QUOTE, // ' + DOUBLE_QUOTE, // " + // HASH, // # + // AMPERSAND, // & + MODULO, // % + SLASH, // / + ASTERISK, // * + PLUS_SIGN, // + + MINUS_SIGN, // + + EQUALS_SIGN, // = + COLON, // : + LESS_THAN, // < + GREATER_THAN, // > + + LESS_THAN_OR_EQUAL, // <= + GREATER_THAN_OR_EQUAL, // >= + EQUALS, // == + NOT_EQUALS, // != + CONJUNCTION, // && + DISJUNCTION, // || + INLINE_COMMENT, // // // default type keywords I8, @@ -50,27 +54,27 @@ namespace sigma { CHAR, // control flow - RET, // ret - IF, // if - ELSE, // else - + RET, // ret + IF, // if + ELSE, // else + // other keywords - NAMESPACE, // namespace - CAST, // cast - SIZEOF, // sizeof + NAMESPACE, // namespace + CAST, // cast + SIZEOF, // sizeof // literals - SIGNED_LITERAL, // 0 - UNSIGNED_LITERAL, // 0u - F32_LITERAL, // 0.0f - F64_LITERAL, // 0.0 - HEXADECIMAL_LITERAL, // 0x / 0X - BINARY_LITERAL, // 0b / 0B - STRING_LITERAL, // "text" - CHARACTER_LITERAL, // 'x' - BOOL_LITERAL_TRUE, // true - BOOL_LITERAL_FALSE, // false - NULL_LITERAL, // null + SIGNED_LITERAL, // 0 + UNSIGNED_LITERAL, // 0u + F32_LITERAL, // 0.0f + F64_LITERAL, // 0.0 + HEXADECIMAL_LITERAL, // 0x / 0X + BINARY_LITERAL, // 0b / 0B + STRING_LITERAL, // "text" + CHARACTER_LITERAL, // 'x' + BOOL_LITERAL_TRUE, // true + BOOL_LITERAL_FALSE, // false + NULL_LITERAL, // null IDENTIFIER, END_OF_FILE diff --git a/source/tokenizer/tokenizer.h b/source/tokenizer/tokenizer.h index 03052b7a..dff41478 100644 --- a/source/tokenizer/tokenizer.h +++ b/source/tokenizer/tokenizer.h @@ -62,32 +62,37 @@ namespace sigma { { "true", token_type::BOOL_LITERAL_TRUE }, { "false", token_type::BOOL_LITERAL_FALSE }, - { "null", token_type::NULL_LITERAL }, + { "null", token_type::NULL_LITERAL }, }; const std::unordered_map m_special_tokens = { - { "(" , token_type::LEFT_PARENTHESIS }, - { ")" , token_type::RIGHT_PARENTHESIS }, - { "{" , token_type::LEFT_BRACE }, - { "}" , token_type::RIGHT_BRACE }, - { "[" , token_type::LEFT_BRACKET }, - { "]" , token_type::RIGHT_BRACKET }, - { "," , token_type::COMMA }, - { ";" , token_type::SEMICOLON }, - { "'" , token_type::SINGLE_QUOTE }, - { "\"" , token_type::DOUBLE_QUOTE }, - { "%" , token_type::MODULO }, - { "/" , token_type::SLASH }, - { "*" , token_type::ASTERISK }, - { "+" , token_type::PLUS_SIGN }, - { "-" , token_type::MINUS_SIGN }, - { "=" , token_type::EQUALS_SIGN }, - { ":" , token_type::COLON }, - { "<" , token_type::LESS_THAN }, - { ">" , token_type::GREATER_THAN }, - { "&&" , token_type::CONJUNCTION }, - { "||" , token_type::DISJUNCTION }, - { "//" , token_type::INLINE_COMMENT }, + { "(" , token_type::LEFT_PARENTHESIS }, + { ")" , token_type::RIGHT_PARENTHESIS }, + { "{" , token_type::LEFT_BRACE }, + { "}" , token_type::RIGHT_BRACE }, + { "[" , token_type::LEFT_BRACKET }, + { "]" , token_type::RIGHT_BRACKET }, + { "," , token_type::COMMA }, + { ";" , token_type::SEMICOLON }, + { "'" , token_type::SINGLE_QUOTE }, + { "\"" , token_type::DOUBLE_QUOTE }, + { "%" , token_type::MODULO }, + { "/" , token_type::SLASH }, + { "*" , token_type::ASTERISK }, + { "+" , token_type::PLUS_SIGN }, + { "-" , token_type::MINUS_SIGN }, + { "=" , token_type::EQUALS_SIGN }, + { ":" , token_type::COLON }, + { "<" , token_type::LESS_THAN }, + { ">" , token_type::GREATER_THAN }, + + { "&&", token_type::CONJUNCTION }, + { "||", token_type::DISJUNCTION }, + { "//", token_type::INLINE_COMMENT }, + { "<=", token_type::LESS_THAN_OR_EQUAL }, + { ">=", token_type::GREATER_THAN_OR_EQUAL }, + { "==", token_type::EQUALS }, + { "!=", token_type::NOT_EQUALS }, }; }; } // namespace sigma