Chord literals support

This commit is contained in:
Robert Bendun 2022-05-02 19:00:11 +02:00
parent 74f4393d6a
commit d6edc2e6e4
4 changed files with 70 additions and 4 deletions

View File

@ -1,5 +1,7 @@
#include <musique.hh>
constexpr std::string_view Notes_Symbols = "abcedefgh";
auto Lexer::next_token() -> Result<Token>
{
while (consume_if(unicode::is_space)) {}
@ -40,6 +42,51 @@ auto Lexer::next_token() -> Result<Token>
return { Token::Type::Numeric, finish(), token_location };
}
if (consume_if([](u32 ch) { return Notes_Symbols.find(ch) != std::string_view::npos; })) {
// chord declaration
constexpr u8 Expect_Number = 0b01;
constexpr u8 Expect_Move = 0b10;
constexpr u8 Expect_Number_Or_Move = 0b11;
auto current = Expect_Number;
std::string_view accepted_digits = "12357";
usize digit_cursor = 0;
for (;;) {
if ((current & Expect_Move) == Expect_Move
&& consume_if([](u32 c) { return c == ',' || c == '\''; })
) {
current = Expect_Number;
continue;
}
if ((current & Expect_Number) == Expect_Number) {
bool found = false;
for (; digit_cursor < accepted_digits.size(); ++digit_cursor) {
if (consume_if([&](u32 c) { return u32(accepted_digits[digit_cursor]) == c; })) {
found = true;
break;
}
}
if (found) {
current = digit_cursor < accepted_digits.size()
? Expect_Number_Or_Move
: Expect_Move;
continue;
}
}
break;
}
if (unicode::is_letter(peek())) {
assert(false && "symbols are not implemented yet");
}
return { Token::Type::Chord, finish(), token_location };
}
return errors::unrecognized_character(peek(), token_location);
}

View File

@ -113,6 +113,7 @@ namespace unicode
bool is_digit(u32 digit);
bool is_space(u32 space);
bool is_letter(u32 letter);
}
namespace utf8
@ -183,7 +184,7 @@ struct Lexer
// Finds next rune in source and returns it, advancing the string
auto consume() -> u32;
inline auto consume_if(auto test) -> u32
inline auto consume_if(auto test) -> bool
{
return test(peek()) && (consume(), true);
}

View File

@ -27,10 +27,13 @@ static void expect_token_type_and_value(
{
Lexer lexer{source};
auto result = lexer.next_token();
expect(result.has_value() >> fatal, sl) << "have not parsed any tokens";
expect(result.has_value(), sl) << "have not parsed any tokens";
if (result.has_value()) {
expect(eq(under(result->type), under(expected_type)), sl) << "different token type then expected";
expect(eq(result->source, expected), sl) << "tokenized source is not equal to original";
}
}
static void expect_token_type_and_value(
Token::Type expected_type,
@ -86,4 +89,13 @@ suite lexer_test = [] {
expect_token_type_and_location(Token::Type::Numeric, "\n123", Location::at(2, 1));
expect_token_type_and_location(Token::Type::Numeric, "\n 123", Location::at(2, 3));
};
"Chord literals"_test = [] {
expect_token_type_and_value(Token::Type::Chord, "c1");
expect_token_type_and_value(Token::Type::Chord, "d1257");
expect_token_type_and_value(Token::Type::Chord, "e1'");
expect_token_type_and_value(Token::Type::Chord, "g127");
expect_token_type_and_value(Token::Type::Chord, "f1'2'3'5'7'");
expect_token_type_and_value(Token::Type::Chord, "b1,2,5,7,");
};
};

View File

@ -97,3 +97,9 @@ bool unicode::is_space(u32 space)
}
return false;
}
bool unicode::is_letter(u32 letter)
{
// TODO Unicode letters handling
return std::isalpha(letter);
}