Skip to content

Commit

Permalink
list accessor in expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
MaksimShagov committed Apr 29, 2024
1 parent bea0308 commit aafbf34
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
1 change: 1 addition & 0 deletions compiler/include/compiler/ast/node_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enum class NodeType {
VariableName,
WhileStatement,
ListStatement,
ListAccessor,
};

} // namespace ast
3 changes: 3 additions & 0 deletions compiler/lib/ast/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ void Node::dump(std::ostream &stream, int depth) const {
case NodeType::ListStatement:
stream << "ListStatement\n";
break;
case NodeType::ListAccessor:
stream << "ListAccessor\n";
break;
default:
stream << "Unknown\n";
}
Expand Down
28 changes: 24 additions & 4 deletions compiler/lib/frontend/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ bool isFunctionCall(const TokenIterator &tokenIter) {
return tokenIter->type == TokenType::Identifier && std::next(tokenIter)->is(Operator::LeftBrace);
}

bool isListAccessor(const TokenIterator &tokenIter) {

Check failure

Code scanning / clang-tidy

no header providing "lexer::TokenIterator" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "lexer::TokenIterator" is directly included [misc-include-cleaner,-warnings-as-errors]
return tokenIter->type == TokenType::Identifier && std::next(tokenIter)->is(Operator::RectLeftBrace);

Check failure

Code scanning / clang-tidy

no header providing "std::next" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "std::next" is directly included [misc-include-cleaner,-warnings-as-errors]
}

void buildExpressionSubtree(std::stack<SubExpression> postfixForm, ast::Node::Ptr root, ErrorBuffer &errors) {
ast::Node::Ptr currNode = root;
while (!postfixForm.empty()) {
Expand Down Expand Up @@ -240,10 +244,11 @@ void buildExpressionSubtree(std::stack<SubExpression> postfixForm, ast::Node::Pt
}
}
} else {
ast::Node::Ptr funcCallNode = std::get<ast::Node::Ptr>(subexpr);
assert(funcCallNode->type == ast::NodeType::FunctionCall);
funcCallNode->parent = currNode;
currNode->children.push_front(funcCallNode);
// can be FunctionCall node and list ListAccessor
ast::Node::Ptr callNode = std::get<ast::Node::Ptr>(subexpr);
assert(callNode->type == ast::NodeType::FunctionCall or callNode->type == ast::NodeType::ListAccessor);
callNode->parent = currNode;
currNode->children.push_front(callNode);
}
while (currNode->children.size() >= getOperandCount(getOperationType(*currNode)))
currNode = currNode->parent;
Expand Down Expand Up @@ -289,6 +294,21 @@ std::stack<SubExpression> generatePostfixForm(TokenIterator tokenIterBegin, Toke
tokenIter = argsEnd;
continue;
}
if (isListAccessor(tokenIter)) {
ast::Node::Ptr listAccessorNode = std::make_shared<ast::Node>(ast::NodeType::ListAccessor);

Check failure

Code scanning / clang-tidy

no header providing "std::make_shared" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "std::make_shared" is directly included [misc-include-cleaner,-warnings-as-errors]
auto node = ParserContext::pushChildNode(listAccessorNode, ast::NodeType::VariableName, token.ref);
node->value = token.id();
auto exprBegin = std::next(tokenIter, 2);

Check failure

Code scanning / clang-tidy

no header providing "std::next" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "std::next" is directly included [misc-include-cleaner,-warnings-as-errors]
auto it = exprBegin;
while (!it->is(Operator::RectRightBrace))
it++;
std::stack<SubExpression> argPostfixForm = generatePostfixForm(exprBegin, it, errors);

Check failure

Code scanning / clang-tidy

no header providing "std::stack" is directly included [misc-include-cleaner,-warnings-as-errors] Error

no header providing "std::stack" is directly included [misc-include-cleaner,-warnings-as-errors]
auto exprNode = ParserContext::pushChildNode(listAccessorNode, ast::NodeType::Expression, token.ref);
buildExpressionSubtree(argPostfixForm, exprNode, errors);
postfixForm.push(listAccessorNode);

Check failure

Code scanning / clang-tidy

use emplace instead of push [modernize-use-emplace,-warnings-as-errors] Error

use emplace instead of push [modernize-use-emplace,-warnings-as-errors]
tokenIter = it++;
continue;
}
OperationType opType = getOperationType(token);
ExpressionTokenType expType = getExpressionTokenType(token);
if (expType == ExpressionTokenType::Operand) {
Expand Down
37 changes: 37 additions & 0 deletions compiler/tests/frontend/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,3 +545,40 @@ TEST(Parser, can_parse_list_defenition) {
" IntegerLiteralValue: 3\n";
ASSERT_EQ(expected, tree.dump());
}

TEST(Parser, can_parse_list_access) {
StringVec source = {
"def main() -> None:",
" mylist : list[int] = [1, 2, 3]",
" x : int = mylist[0]",
};
TokenList tokens = Lexer::process(source);
SyntaxTree tree = Parser::process(tokens);
std::string expected = "ProgramRoot\n"
" FunctionDefinition\n"
" FunctionName: main\n"
" FunctionArguments\n"
" FunctionReturnType: NoneType\n"
" BranchRoot\n"
" VariableDeclaration\n"
" TypeName: ListType\n"
" TypeName: IntType\n"
" VariableName: mylist\n"
" Expression\n"
" ListStatement\n"
" Expression\n"
" IntegerLiteralValue: 1\n"
" Expression\n"
" IntegerLiteralValue: 2\n"
" Expression\n"
" IntegerLiteralValue: 3\n"
" VariableDeclaration\n"
" TypeName: IntType\n"
" VariableName: x\n"
" Expression\n"
" ListAccessor\n"
" VariableName: mylist\n"
" Expression\n"
" IntegerLiteralValue: 0\n";
ASSERT_EQ(expected, tree.dump());
}

0 comments on commit aafbf34

Please sign in to comment.