Added lexing and parsing for single quote
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				ci/woodpecker/push/workflow Pipeline was successful
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	ci/woodpecker/push/workflow Pipeline was successful
				
			This commit is contained in:
		@@ -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