Skip to content

Commit

Permalink
Merge pull request #4 from plorth/v2
Browse files Browse the repository at this point in the history
Redesign word definitions
  • Loading branch information
RauliL authored May 12, 2023
2 parents 61fe00a + 06b12e4 commit 2da4c01
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 81 deletions.
74 changes: 32 additions & 42 deletions include/plorth/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,9 @@ namespace plorth::parser
case '"':
case '\'':
return parse_string(current, end, position);

case ':':
return parse_word(current, end, position);
}

return parse_symbol(current, end, position);
return parse_symbol_or_word(current, end, position);
}

/**
Expand Down Expand Up @@ -631,76 +628,69 @@ namespace plorth::parser
}

/**
* Attempts to parse word definition AST token.
* Attempts to parse either symbol or word definition AST token.
*
* \param current Iterator pointing to current position in source code.
* \param end Iterator pointing to end of the source code.
* \param position Current source code position.
*/
template<class IteratorT>
parse_word_result parse_word(
parse_token_result parse_symbol_or_word(
IteratorT& current,
const IteratorT& end,
struct position& position
)
{
struct position word_position;
ast::quote::container_type children;
struct position symbol_or_word_position;
std::u32string buffer;

if (utils::skip_whitespace(current, end, position))
{
return parse_word_result::error({
return parse_symbol_result::error({
position,
U"Unexpected end of input; Missing word."
U"Unexpected end of input; Missing symbol or word definition."
});
}

word_position = position;
symbol_or_word_position = position;

if (!utils::peek_advance(current, end, position, U':'))
if (!utils::isword(*current))
{
return parse_word_result::error({
word_position,
U"Unexpected input; Missing word."
return parse_symbol_result::error({
symbol_or_word_position,
U"Unexpected input; Missing symbol or word definition."
});
}

const auto symbol_result = parse_symbol(current, end, position);

if (!symbol_result)
do
{
return parse_word_result::error(*symbol_result.error());
buffer.append(1, utils::advance(current, position));
}
while (current < end && utils::isword(*current));

for (;;)
if (!buffer.compare(U"->"))
{
if (utils::skip_whitespace(current, end, position))
const auto symbol_result = parse_symbol(
current,
end,
symbol_or_word_position
);

if (!symbol_result)
{
return parse_word_result::error({
word_position,
U"Unterminated word; Missing `;'."
});
return parse_token_result::error(*symbol_result.error());
}
else if (utils::peek_advance(current, end, position, U';'))
{
break;
} else {
const auto child_result = parse_token(current, end, position);

if (!child_result)
{
return parse_word_result::error(*child_result.error());
}
children.push_back(*child_result.value());
}
return parse_token_result::ok(
std::make_shared<ast::word>(
symbol_or_word_position,
*symbol_result.value()
)
);
}

return parse_word_result::ok(
std::make_shared<ast::word>(
word_position,
*symbol_result.value(),
std::make_shared<ast::quote>(word_position, children)
)
return parse_token_result::ok(
std::make_shared<ast::symbol>(symbol_or_word_position, buffer)
);
}
}
17 changes: 2 additions & 15 deletions include/plorth/parser/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,16 +260,13 @@ namespace plorth::parser::ast
{
public:
using symbol_type = std::shared_ptr<class symbol>;
using quote_type = std::shared_ptr<class quote>;

explicit word(
const struct position& position,
const symbol_type& symbol,
const quote_type& quote
const symbol_type& symbol
)
: token(position)
, m_symbol(symbol)
, m_quote(quote) {}
, m_symbol(symbol) {}

inline enum type type() const
{
Expand All @@ -284,18 +281,8 @@ namespace plorth::parser::ast
return m_symbol;
}

/**
* Returns contents of the word.
*/
inline const quote_type& quote() const
{
return m_quote;
}

private:
/** Identifier of the word. */
const symbol_type m_symbol;
/** Contents of the word. */
const quote_type m_quote;
};
}
2 changes: 1 addition & 1 deletion include/plorth/parser/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ namespace plorth::parser::utils
static inline bool isword(char32_t c)
{
return c != '(' && c != ')' && c != '[' && c != ']' && c != '{'
&& c != '}' && c != ':' && c != ';' && c != ','
&& c != '}' && c != ','
&& peelo::unicode::ctype::isgraph(c);
}
}
2 changes: 1 addition & 1 deletion test/test_token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static void test_string_with_apostrophe()

static void test_word()
{
const auto result = parse(U": foo bar ;");
const auto result = parse(U"-> foo");

assert(!!result);
assert((*result.value())->type() == token::type::word);
Expand Down
4 changes: 2 additions & 2 deletions test/test_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ static void test_isword()
assert(!isword(U']'));
assert(!isword(U'{'));
assert(!isword(U'}'));
assert(!isword(U':'));
assert(!isword(U';'));
assert(!isword(U','));
assert(!isword(U' '));

assert(isword(U'a'));
assert(isword(U'-'));
assert(isword(U'\u00e4'));
assert(isword(U':'));
assert(isword(U';'));
}

int main(int argc, char** argv)
Expand Down
4 changes: 1 addition & 3 deletions test/test_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ static void test_visit_word()
{
test_visitor visitor;
auto symbol = std::make_shared<class symbol>(position, U"");
const quote::container_type children = {};
auto quote = std::make_shared<class quote>(position, children);
auto token = std::make_shared<word>(position, symbol, quote);
auto token = std::make_shared<word>(position, symbol);
bool flag = false;

visitor.visit(token, flag);
Expand Down
35 changes: 18 additions & 17 deletions test/test_word.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@

#include <plorth/parser.hpp>

using plorth::parser::parse_word;
using plorth::parser::parse_symbol_or_word;
using plorth::parser::ast::token;

static auto parse(const std::u32string& source)
{
auto begin = std::cbegin(source);
const auto end = std::cend(source);
plorth::parser::position position;

return parse_word<std::u32string::const_iterator>(begin, end, position);
return parse_symbol_or_word<std::u32string::const_iterator>(
begin,
end,
position
);
}

static void test_eof_before_the_word()
Expand All @@ -21,42 +26,38 @@ static void test_eof_before_the_word()
assert(!result);
}

static void test_no_colon_found()
static void test_no_arrow_found()
{
const auto result = parse(U"invalid");

assert(!result);
assert(result);
assert((*result.value())->type() == token::type::symbol);
}

static void test_no_symbol_found()
{
const auto result = parse(U": [ bar ;");

assert(!result);
}

static void test_unterminated_word()
{
const auto result = parse(U": foo bar baz");
const auto result = parse(U"->");

assert(!result);
}

static void test_parse()
{
const auto result = parse(U": foo bar baz ;");
const auto result = parse(U"-> foo");

assert(!!result);
assert((*result.value())->symbol()->id() == U"foo");
assert((*result.value())->quote()->children().size() == 2);
assert(
std::static_pointer_cast<plorth::parser::ast::word>(
(*result.value())
)->symbol()->id() == U"foo"
);
}

int main(int argc, char** argv)
{
test_eof_before_the_word();
test_no_colon_found();
test_no_arrow_found();
test_no_symbol_found();
test_unterminated_word();
test_parse();

return EXIT_SUCCESS;
Expand Down

0 comments on commit 2da4c01

Please sign in to comment.