Compare commits
2 Commits
ed791d96f2
...
01246cc0e1
Author | SHA1 | Date | |
---|---|---|---|
01246cc0e1 | |||
a13dbcaa77 |
@@ -63,7 +63,7 @@ Woodpecker CI/CD system is integrated.
|
|||||||
Currently using Catch2 for unit testing.
|
Currently using Catch2 for unit testing.
|
||||||
|
|
||||||
- Lexing - complete, more token types may be added as necessary
|
- Lexing - complete, more token types may be added as necessary
|
||||||
- Parsing - This is the next step.
|
- Parsing - the main steps are done, but things may change as time progresses
|
||||||
- Optimizations -
|
- Optimizations -
|
||||||
- Emitting Bytecode - the goal.
|
- Emitting Bytecode - the goal.
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@ enum class TokenType {
|
|||||||
String,
|
String,
|
||||||
Int,
|
Int,
|
||||||
Double,
|
Double,
|
||||||
|
Quote,
|
||||||
End
|
End
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
std::optional<LispValue> parse_one();
|
std::optional<LispValue> parse_one();
|
||||||
|
LispValue parse_quote();
|
||||||
LispValue parse_list();
|
LispValue parse_list();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// we're using a pure variant as our value type.
|
// we're using a pure variant as our value type.
|
||||||
struct Integer {int64_t value;};
|
struct Integer {int64_t value;};
|
||||||
|
@@ -12,6 +12,7 @@ std::ostream &operator<<(std::ostream &os, Token const &t) {
|
|||||||
case TokenType::OpenParen: os << "OpenParen)"; break;
|
case TokenType::OpenParen: os << "OpenParen)"; break;
|
||||||
case TokenType::CloseParen: os << "CloseParen)"; break;
|
case TokenType::CloseParen: os << "CloseParen)"; break;
|
||||||
case TokenType::Dollar: os << "Dollar)"; break;
|
case TokenType::Dollar: os << "Dollar)"; break;
|
||||||
|
case TokenType::Quote: os << "QUOTE)"; break;
|
||||||
case TokenType::Symbol: os << "Symbol, " << get<string>(*t.value) << ")"; break;
|
case TokenType::Symbol: os << "Symbol, " << get<string>(*t.value) << ")"; break;
|
||||||
case TokenType::String: os << "String, \"" << get<string>(*t.value) << "\")"; break;
|
case TokenType::String: os << "String, \"" << get<string>(*t.value) << "\")"; break;
|
||||||
case TokenType::Int: os << "Int, " << get<int64_t>(*t.value) << ")"; break;
|
case TokenType::Int: os << "Int, " << get<int64_t>(*t.value) << ")"; break;
|
||||||
@@ -139,6 +140,7 @@ Token Lexer::next() {
|
|||||||
case '(': return {TokenType::OpenParen, nullopt};
|
case '(': return {TokenType::OpenParen, nullopt};
|
||||||
case ')': return {TokenType::CloseParen, nullopt};
|
case ')': return {TokenType::CloseParen, nullopt};
|
||||||
case '$': return {TokenType::Dollar, nullopt};
|
case '$': return {TokenType::Dollar, nullopt};
|
||||||
|
case '\'': return {TokenType::Quote, nullopt};
|
||||||
default:
|
default:
|
||||||
ss.unget();
|
ss.unget();
|
||||||
return lexNonSpecial();
|
return lexNonSpecial();
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include <exception>
|
||||||
#include <lex.hpp>
|
#include <lex.hpp>
|
||||||
|
|
||||||
#include <parse.hpp>
|
#include <parse.hpp>
|
||||||
@@ -13,6 +14,10 @@ void Parser::feed(Lexer l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token Parser::get_token() {
|
Token Parser::get_token() {
|
||||||
|
if (ts.empty()) {
|
||||||
|
cerr << "Parser::get_token: Token requested at input end." << endl;
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
Token t = ts.front();
|
Token t = ts.front();
|
||||||
ts.pop_front();
|
ts.pop_front();
|
||||||
return t;
|
return t;
|
||||||
@@ -29,6 +34,22 @@ Symbol Parser::make_symbol(string s) {
|
|||||||
return Symbol {s};
|
return Symbol {s};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LispValue Parser::parse_quote() {
|
||||||
|
// in regular lisps, a quote gets expanded to a (quote) form.
|
||||||
|
// i.e. 'a is actually (QUOTE A). This prevents the symbol from being
|
||||||
|
// evaluated.
|
||||||
|
// This is the same way we'll handle quotes for now, because I can't
|
||||||
|
// think of anything else.
|
||||||
|
List l;
|
||||||
|
|
||||||
|
l.list.push_back(make_symbol("QUOTE"));
|
||||||
|
auto next = parse_one();
|
||||||
|
// this is guaranteed to work, because if we do not have enough tokens
|
||||||
|
// to constitute another value Parser::get_token will throw an exception
|
||||||
|
l.list.push_back(*next);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
optional<LispValue> Parser::parse_one() {
|
optional<LispValue> Parser::parse_one() {
|
||||||
Token t = get_token();
|
Token t = get_token();
|
||||||
switch (t.type) {
|
switch (t.type) {
|
||||||
@@ -38,6 +59,7 @@ optional<LispValue> Parser::parse_one() {
|
|||||||
case TokenType::Symbol: return make_symbol(get<string>(*t.value));
|
case TokenType::Symbol: return make_symbol(get<string>(*t.value));
|
||||||
case TokenType::OpenParen: return parse_list();
|
case TokenType::OpenParen: return parse_list();
|
||||||
case TokenType::CloseParen: throw "whatever";
|
case TokenType::CloseParen: throw "whatever";
|
||||||
|
case TokenType::Quote: return parse_quote();
|
||||||
|
|
||||||
// I don't know what this will actually do, in theory maybe just like the OpenParen,
|
// I don't know what this will actually do, in theory maybe just like the OpenParen,
|
||||||
// but parses things in a different namespace? unimplemented for now.
|
// but parses things in a different namespace? unimplemented for now.
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <value.hpp>
|
#include <value.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
Reference in New Issue
Block a user