Parse function somewhat correctly
This commit is contained in:
parent
31c697a097
commit
8520404fb1
@ -15,12 +15,16 @@ namespace AST {
|
|||||||
class IntLiteralExpression : public Expression {
|
class IntLiteralExpression : public Expression {
|
||||||
private:
|
private:
|
||||||
int m_value;
|
int m_value;
|
||||||
|
public:
|
||||||
|
IntLiteralExpression(int value) : m_value{ value } {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ReturnStatement : public Statement {
|
class ReturnStatement : public Statement {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Expression> m_expr;
|
std::unique_ptr<Expression> m_expr;
|
||||||
|
public:
|
||||||
|
ReturnStatement(std::unique_ptr<Expression> expr) : m_expr{ std::move(expr) } {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TopLevelStatement : public Node {};
|
class TopLevelStatement : public Node {};
|
||||||
@ -33,7 +37,7 @@ namespace AST {
|
|||||||
std::vector<std::unique_ptr<Statement>> m_statements;
|
std::vector<std::unique_ptr<Statement>> m_statements;
|
||||||
public:
|
public:
|
||||||
Function(
|
Function(
|
||||||
Type* return_ty,
|
std::unique_ptr<Type> return_ty,
|
||||||
std::vector<std::pair<std::string, std::unique_ptr<Type>>> params,
|
std::vector<std::pair<std::string, std::unique_ptr<Type>>> params,
|
||||||
std::string name,
|
std::string name,
|
||||||
std::vector<std::unique_ptr<Statement>> statements)
|
std::vector<std::unique_ptr<Statement>> statements)
|
||||||
@ -51,6 +55,8 @@ namespace AST {
|
|||||||
class FundamentalType : public Type {
|
class FundamentalType : public Type {
|
||||||
private:
|
private:
|
||||||
FundamentalTypeKind m_ty;
|
FundamentalTypeKind m_ty;
|
||||||
|
public:
|
||||||
|
FundamentalType(FundamentalTypeKind kind) : m_ty{ kind } {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,6 +59,7 @@ int main() {
|
|||||||
statements.push_back(statement.unwrap());
|
statements.push_back(statement.unwrap());
|
||||||
statement = parsing::parse_top_level_statement(stream);
|
statement = parsing::parse_top_level_statement(stream);
|
||||||
}
|
}
|
||||||
|
stream.expect(token::Type::Eof);
|
||||||
|
|
||||||
// LLVM Hello World
|
// LLVM Hello World
|
||||||
// llvm_hello_world();
|
// llvm_hello_world();
|
||||||
|
|||||||
@ -2,8 +2,86 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace parsing {
|
namespace parsing {
|
||||||
|
namespace {
|
||||||
|
Result<std::unique_ptr<AST::Type>, std::string> parse_type(token::TokenStream& stream) {
|
||||||
|
token::TokenStream inner{ stream };
|
||||||
|
try {
|
||||||
|
auto token = inner.expect(token::Type::Ident);
|
||||||
|
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
|
||||||
|
auto ty = new AST::FundamentalType{ AST::FundamentalTypeKind::Int };
|
||||||
|
return std::unique_ptr<AST::Type> {ty};
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
return std::string{ error.what() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<std::unique_ptr<AST::Expression>, std::string> parse_expression(token::TokenStream& stream) {
|
||||||
|
token::TokenStream inner{ stream };
|
||||||
|
try {
|
||||||
|
auto token = inner.next();
|
||||||
|
if (token.type == token::Type::LiteralInt) {
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
|
||||||
|
auto expr = new AST::IntLiteralExpression{ 5 };
|
||||||
|
return std::unique_ptr<AST::Expression>{expr};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Expected expression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
return std::string{ error.what() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<std::unique_ptr<AST::Statement>, std::string> parse_statement(token::TokenStream& stream) {
|
||||||
|
token::TokenStream inner{ stream };
|
||||||
|
try {
|
||||||
|
if (inner.peek().type == token::Type::ReturnKeyword) {
|
||||||
|
inner.next();
|
||||||
|
auto expression = parse_expression(inner).unwrap();
|
||||||
|
inner.expect(token::Type::Symbol, ";");
|
||||||
|
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
|
||||||
|
auto ret = new AST::ReturnStatement{ std::move(expression) };
|
||||||
|
return std::unique_ptr<AST::Statement>{ ret };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Expected return-keyword");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
return std::string{ error.what() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Result<std::unique_ptr<AST::TopLevelStatement>, std::string> parse_top_level_statement(token::TokenStream& stream) {
|
Result<std::unique_ptr<AST::TopLevelStatement>, std::string> parse_top_level_statement(token::TokenStream& stream) {
|
||||||
auto fun = new AST::Function{ nullptr, {}, "main", {} };
|
token::TokenStream inner{ stream };
|
||||||
return Result<std::unique_ptr<AST::TopLevelStatement>, std::string>{ std::unique_ptr<AST::TopLevelStatement>{ fun } };
|
try {
|
||||||
|
auto type = parse_type(inner).unwrap();
|
||||||
|
auto name_token = inner.expect(token::Type::Ident);
|
||||||
|
inner.expect(token::Type::Symbol, "(");
|
||||||
|
inner.expect(token::Type::Symbol, ")");
|
||||||
|
inner.expect(token::Type::Symbol, "{");
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<AST::Statement>> statements{};
|
||||||
|
statements.push_back(parse_statement(inner).unwrap());
|
||||||
|
|
||||||
|
inner.expect(token::Type::Symbol, "}");
|
||||||
|
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
|
||||||
|
auto fun = new AST::Function{ std::move(type), {}, "main", std::move(statements) };
|
||||||
|
return std::unique_ptr<AST::TopLevelStatement>{ fun };
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
return std::string(error.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +64,9 @@ namespace token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token TokenStream::next() {
|
Token TokenStream::next() {
|
||||||
return this->peek(++m_position);
|
token::Token got = this->peek(0);
|
||||||
|
m_position++;
|
||||||
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token TokenStream::expect(Type type) {
|
Token TokenStream::expect(Type type) {
|
||||||
@ -75,6 +77,14 @@ namespace token {
|
|||||||
throw std::runtime_error("Expected " + type_name(type) + ", got " + next.formatted());
|
throw std::runtime_error("Expected " + type_name(type) + ", got " + next.formatted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token TokenStream::expect(Type type, std::string_view content) {
|
||||||
|
auto next = this->next();
|
||||||
|
if (next.type == type && next.content == content) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Expected " + type_name(type) + "(" + std::string{ content } + "), got " + next.formatted());
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<token::Token> tokenize(std::string_view text) {
|
std::vector<token::Token> tokenize(std::string_view text) {
|
||||||
std::vector<token::Token> tokens{};
|
std::vector<token::Token> tokens{};
|
||||||
|
|
||||||
@ -108,7 +118,8 @@ namespace token {
|
|||||||
content += c;
|
content += c;
|
||||||
c = text[++i];
|
c = text[++i];
|
||||||
} while (iswhitespace(c));
|
} while (iswhitespace(c));
|
||||||
tokens.push_back(token::Token{ token::Type::Whitespace, content });
|
// tokens.push_back(token::Token{ token::Type::Whitespace, content });
|
||||||
|
// Just skip whitespace tokens
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tokens.push_back(token::Token{ token::Type::Symbol, std::string{c} });
|
tokens.push_back(token::Token{ token::Type::Symbol, std::string{c} });
|
||||||
|
|||||||
@ -30,13 +30,14 @@ namespace token {
|
|||||||
class TokenStream {
|
class TokenStream {
|
||||||
private:
|
private:
|
||||||
std::vector<Token>& m_tokens;
|
std::vector<Token>& m_tokens;
|
||||||
int m_position;
|
|
||||||
public:
|
public:
|
||||||
|
int m_position;
|
||||||
TokenStream(std::vector<Token>& tokens);
|
TokenStream(std::vector<Token>& tokens);
|
||||||
Token peek(int length);
|
Token peek(int length);
|
||||||
Token peek();
|
Token peek();
|
||||||
Token next();
|
Token next();
|
||||||
Token expect(Type type);
|
Token expect(Type type);
|
||||||
|
Token expect(Type type, std::string_view content);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, Token& token);
|
std::ostream& operator<<(std::ostream& stream, Token& token);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user