blob: 2ba12adfd941d0721ae9c3fdf77477c71fac665a [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/shell/parser/error.h"
#include <gtest/gtest.h>
#include "src/developer/shell/parser/ast_test.h"
#include "src/developer/shell/parser/combinators.h"
#include "src/developer/shell/parser/text_match.h"
namespace shell::parser {
TEST(ErrorTest, Insert) {
const char* kTestString = "smith";
auto result =
Seq(Alt(Token("bob"), ErInsert("Expected bob")), Token("smith"))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(5u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("(E[Expected bob] 'smith')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, Skip) {
const char* kTestString = "bobsmith";
auto result = Seq(Alt(Token("jed"), ErSkip("Unexpected bob", Token("bob"))),
Token("smith"))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(8u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("(E[Unexpected bob] 'smith')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SkipMatchMacro) {
const char* kTestString = "jedbobsmith";
auto result = Seq(Alt(Token("fred"), ErSkip("Unexpected '%MATCH%'", OnePlus(AnyCharBut("s")))),
Token("smith"))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(11u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("(E[Unexpected 'jedbob'] 'smith')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SeqReconnect) {
const char* kTestString = "jedsmith";
auto result = Seq(Alt(Seq(Token("jed"), Alt(Token("fred"), ErInsert("Expected fred"))), Empty),
Alt(Token("smith"), ErInsert("Expected smith")))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(8u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("('jed' E[Expected fred] 'smith')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SeqReconnectThruToken) {
const char* kTestString = "jedsmith";
auto result =
Seq(Token(Alt(Seq(Token("jed"), Alt(Token("fred"), ErInsert("Expected fred"))), Empty)),
Alt(Token("smith"), ErInsert("Expected smith")))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(8u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("(('jed' E[Expected fred]) 'smith')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SeqReconnectFromNull) {
const char* kTestString = "jedbobsmith";
auto result = Seq(
Alt(Seq(Token("jed"), Alt(Token("fred"), ErSkip("Expected fred, got %MATCH%", Token("bob")))),
Empty),
Alt(Token("smith"), ErInsert("Expected smith")))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(11u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("('jed' E[Expected fred, got bob] 'smith')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SeqReconnectMultipleAlt) {
const char* kTestString = "bobbobjeb";
auto result = Seq(Alt(Seq(Token("bob"), ErInsert("Expected smith")),
Seq(Token("bob"), Token("bob"), ErInsert("Expected smith")), Empty),
Token("jeb"))(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(9u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("('bob' 'bob' E[Expected smith] 'jeb')",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SeqReconnectLAssoc) {
const char* kTestString = "a+a++a";
auto result = Seq(
LAssoc<ast::TestNode>(Token("a"), Seq(Token("+"), Alt(Token("a"), ErInsert("Expected a")))),
EOS)(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(6u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("(((('a' '+' 'a') '+' E[Expected a]) '+' 'a'))",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
TEST(ErrorTest, SeqReconnectThroughNT) {
const char* kTestString = "a>!a";
auto result =
Seq(Maybe(Token("!")),
NT<ast::TestNode>(LAssoc<ast::TestNode>(
Token("a"), Seq(Token(">"), Alt(Token("a"), ErSkip("! can't occur here",
Seq(Token("!"), Token("a"))))))),
EOS)(ParseResult(kTestString));
ASSERT_TRUE(result);
EXPECT_EQ(4u, result.offset());
EXPECT_EQ(1u, result.errors());
EXPECT_EQ("((('a' '>' E[! can't occur here])))",
result.Reduce<ast::TestNode>().node()->ToString(kTestString));
}
} // namespace shell::parser