From 01246cc0e1223928f7b3ee1694a4a0c0999cfb77 Mon Sep 17 00:00:00 2001 From: haxala1r Date: Fri, 3 Oct 2025 22:51:46 +0300 Subject: [PATCH] Added lexing and parsing for single quote --- src/include/lex.hpp | 1 + src/include/parse.hpp | 1 + src/include/value.hpp | 2 -- src/lex.cpp | 2 ++ src/parse.cpp | 22 ++++++++++++++++++++++ src/value.cpp | 1 + 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/include/lex.hpp b/src/include/lex.hpp index c24e998..735651f 100644 --- a/src/include/lex.hpp +++ b/src/include/lex.hpp @@ -13,6 +13,7 @@ enum class TokenType { String, Int, Double, + Quote, End }; diff --git a/src/include/parse.hpp b/src/include/parse.hpp index d78f509..0f479bf 100644 --- a/src/include/parse.hpp +++ b/src/include/parse.hpp @@ -20,6 +20,7 @@ private: std::optional parse_one(); + LispValue parse_quote(); LispValue parse_list(); public: diff --git a/src/include/value.hpp b/src/include/value.hpp index 425ddc5..6232eed 100644 --- a/src/include/value.hpp +++ b/src/include/value.hpp @@ -1,11 +1,9 @@ #pragma once -#include #include #include #include #include -#include // we're using a pure variant as our value type. struct Integer {int64_t value;}; diff --git a/src/lex.cpp b/src/lex.cpp index e85e47a..cd35a11 100644 --- a/src/lex.cpp +++ b/src/lex.cpp @@ -12,6 +12,7 @@ std::ostream &operator<<(std::ostream &os, Token const &t) { case TokenType::OpenParen: os << "OpenParen)"; break; case TokenType::CloseParen: os << "CloseParen)"; break; case TokenType::Dollar: os << "Dollar)"; break; + case TokenType::Quote: os << "QUOTE)"; break; case TokenType::Symbol: os << "Symbol, " << get(*t.value) << ")"; break; case TokenType::String: os << "String, \"" << get(*t.value) << "\")"; break; case TokenType::Int: os << "Int, " << get(*t.value) << ")"; break; @@ -139,6 +140,7 @@ Token Lexer::next() { case '(': return {TokenType::OpenParen, nullopt}; case ')': return {TokenType::CloseParen, nullopt}; case '$': return {TokenType::Dollar, nullopt}; + case '\'': return {TokenType::Quote, nullopt}; default: ss.unget(); return lexNonSpecial(); diff --git a/src/parse.cpp b/src/parse.cpp index 8e13357..0900692 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -13,6 +14,10 @@ void Parser::feed(Lexer l) { } Token Parser::get_token() { + if (ts.empty()) { + cerr << "Parser::get_token: Token requested at input end." << endl; + throw exception(); + } Token t = ts.front(); ts.pop_front(); return t; @@ -29,6 +34,22 @@ Symbol Parser::make_symbol(string 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 Parser::parse_one() { Token t = get_token(); switch (t.type) { @@ -38,6 +59,7 @@ optional Parser::parse_one() { case TokenType::Symbol: return make_symbol(get(*t.value)); case TokenType::OpenParen: return parse_list(); 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, // but parses things in a different namespace? unimplemented for now. diff --git a/src/value.cpp b/src/value.cpp index 7426314..e811a3e 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -1,5 +1,6 @@ #include #include +#include template