cpp-peglib/test/test3.cc
2022-06-13 23:16:07 -04:00

316 lines
12 KiB
C++

#include <gtest/gtest.h>
#include <peglib.h>
using namespace peg;
inline bool exact(Grammar &g, const char *d, const char *s) {
auto n = strlen(s);
auto r = g[d].parse(s, n);
return r.ret && r.len == n;
}
#if defined(__cpp_lib_char8_t)
inline bool exact(Grammar &g, const char *d, const char8_t *s) {
auto n = strlen(reinterpret_cast<const char *>(s));
auto r = g[d].parse(s, n);
return r.ret && r.len == n;
}
#endif
inline Grammar &make_peg_grammar() { return ParserGenerator::grammar(); }
TEST(PEGTest, PEG_Grammar) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(
exact(g, "Grammar",
" Definition <- a / ( b c ) / d \n rule2 <- [a-zA-Z][a-z0-9-]+ "));
}
TEST(LeftRecursiveTest, PEG_Definition) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Definition", "Definition <- a / (b c) / d "));
EXPECT_TRUE(exact(g, "Definition", "Definition <- a / b c / d "));
EXPECT_TRUE(exact(g, "Definition", u8"Definitiond ← a "));
EXPECT_FALSE(exact(g, "Definition", "Definition "));
EXPECT_FALSE(exact(g, "Definition", " "));
EXPECT_FALSE(exact(g, "Definition", ""));
EXPECT_FALSE(exact(g, "Definition", "Definition = a / (b c) / d "));
EXPECT_TRUE(exact(g, "Definition", "Macro(param) <- a "));
EXPECT_FALSE(exact(g, "Definition", "Macro (param) <- a "));
}
TEST(LeftRecursiveTest, PEG_Expression) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Expression", "a / (b c) / d "));
EXPECT_TRUE(exact(g, "Expression", "a / b c / d "));
EXPECT_TRUE(exact(g, "Expression", "a b "));
EXPECT_TRUE(exact(g, "Expression", ""));
EXPECT_FALSE(exact(g, "Expression", " "));
EXPECT_FALSE(exact(g, "Expression", " a b "));
// NOTE: The followings are actually allowed in the original Ford's paper...
EXPECT_TRUE(exact(g, "Expression", "a//b "));
EXPECT_TRUE(exact(g, "Expression", "a // b "));
EXPECT_TRUE(exact(g, "Expression", "a / / b "));
}
TEST(LeftRecursiveTest, PEG_Sequence) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Sequence", "a b c d "));
EXPECT_TRUE(exact(g, "Sequence", ""));
EXPECT_FALSE(exact(g, "Sequence", "!"));
EXPECT_FALSE(exact(g, "Sequence", "<-"));
EXPECT_FALSE(exact(g, "Sequence", " a"));
}
TEST(LeftRecursiveTest, PEG_Prefix) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Prefix", "&[a]"));
EXPECT_TRUE(exact(g, "Prefix", "![']"));
EXPECT_FALSE(exact(g, "Prefix", "-[']"));
EXPECT_FALSE(exact(g, "Prefix", ""));
EXPECT_FALSE(exact(g, "Prefix", " a"));
}
TEST(LeftRecursiveTest, PEG_Suffix) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Suffix", "aaa "));
EXPECT_TRUE(exact(g, "Suffix", "aaa? "));
EXPECT_TRUE(exact(g, "Suffix", "aaa* "));
EXPECT_TRUE(exact(g, "Suffix", "aaa+ "));
EXPECT_FALSE(exact(g, "Suffix", "aaa{} "));
EXPECT_TRUE(exact(g, "Suffix", "aaa{10} "));
EXPECT_TRUE(exact(g, "Suffix", "aaa{10,} "));
EXPECT_TRUE(exact(g, "Suffix", "aaa{10,100} "));
EXPECT_TRUE(exact(g, "Suffix", "aaa{,100} "));
EXPECT_TRUE(exact(g, "Suffix", ". + "));
EXPECT_TRUE(exact(g, "Suffix", ". {10} "));
EXPECT_FALSE(exact(g, "Suffix", "?"));
EXPECT_FALSE(exact(g, "Suffix", "+"));
EXPECT_FALSE(exact(g, "Suffix", "{10}"));
EXPECT_FALSE(exact(g, "Suffix", ""));
EXPECT_FALSE(exact(g, "Suffix", " a"));
}
TEST(LeftRecursiveTest, PEG_Primary) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Primary", "_Identifier0_ "));
EXPECT_FALSE(exact(g, "Primary", "_Identifier0_<-"));
EXPECT_TRUE(exact(g, "Primary", "( _Identifier0_ _Identifier1_ )"));
EXPECT_TRUE(exact(g, "Primary", "'Literal String'"));
EXPECT_TRUE(exact(g, "Primary", "\"Literal String\""));
EXPECT_TRUE(exact(g, "Primary", "[a-zA-Z]"));
EXPECT_TRUE(exact(g, "Primary", "."));
EXPECT_FALSE(exact(g, "Primary", ""));
EXPECT_FALSE(exact(g, "Primary", " "));
EXPECT_FALSE(exact(g, "Primary", " a"));
EXPECT_FALSE(exact(g, "Primary", ""));
}
TEST(LeftRecursiveTest, PEG_Identifier) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Identifier", "_Identifier0_ "));
EXPECT_FALSE(exact(g, "Identifier", "0Identifier_ "));
EXPECT_FALSE(exact(g, "Identifier", "Iden|t "));
EXPECT_FALSE(exact(g, "Identifier", " "));
EXPECT_FALSE(exact(g, "Identifier", " a"));
EXPECT_FALSE(exact(g, "Identifier", ""));
}
TEST(LeftRecursiveTest, PEG_IdentStart) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "IdentStart", "_"));
EXPECT_TRUE(exact(g, "IdentStart", "a"));
EXPECT_TRUE(exact(g, "IdentStart", "Z"));
EXPECT_FALSE(exact(g, "IdentStart", ""));
EXPECT_FALSE(exact(g, "IdentStart", " "));
EXPECT_FALSE(exact(g, "IdentStart", "0"));
}
TEST(LeftRecursiveTest, PEG_IdentRest) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "IdentRest", "_"));
EXPECT_TRUE(exact(g, "IdentRest", "a"));
EXPECT_TRUE(exact(g, "IdentRest", "Z"));
EXPECT_FALSE(exact(g, "IdentRest", ""));
EXPECT_FALSE(exact(g, "IdentRest", " "));
EXPECT_TRUE(exact(g, "IdentRest", "0"));
}
TEST(LeftRecursiveTest, PEG_Literal) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Literal", "'abc' "));
EXPECT_TRUE(exact(g, "Literal", "'a\\nb\\tc' "));
EXPECT_TRUE(exact(g, "Literal", "'a\\277\tc' "));
EXPECT_TRUE(exact(g, "Literal", "'a\\77\tc' "));
EXPECT_FALSE(exact(g, "Literal", "'a\\80\tc' "));
EXPECT_TRUE(exact(g, "Literal", "'\n' "));
EXPECT_TRUE(exact(g, "Literal", "'a\\'b' "));
EXPECT_FALSE(exact(g, "Literal", "'a'b' "));
EXPECT_FALSE(exact(g, "Literal", "'a\"'b' "));
EXPECT_TRUE(exact(g, "Literal", "\"'\\\"abc\\\"'\" "));
EXPECT_FALSE(exact(g, "Literal", "\"'\"abc\"'\" "));
EXPECT_FALSE(exact(g, "Literal", "abc"));
EXPECT_FALSE(exact(g, "Literal", ""));
EXPECT_FALSE(exact(g, "Literal", "\\"));
EXPECT_TRUE(exact(g, "Literal", u8"'日本語'"));
EXPECT_TRUE(exact(g, "Literal", u8"\"日本語\""));
EXPECT_FALSE(exact(g, "Literal", u8"日本語"));
}
TEST(LeftRecursiveTest, PEG_Class) {
auto g = ParserGenerator::grammar();
EXPECT_FALSE(
exact(g, "Class", "[]")); // NOTE: This is different from the Brian Ford's
// paper, but same as RegExp
EXPECT_TRUE(exact(g, "Class", "[a]"));
EXPECT_TRUE(exact(g, "Class", "[a-z]"));
EXPECT_TRUE(exact(g, "Class", "[az]"));
EXPECT_TRUE(exact(g, "Class", "[a-zA-Z-]"));
EXPECT_TRUE(exact(g, "Class", "[a-zA-Z-0-9]"));
EXPECT_TRUE(exact(g, "Class", "[a-]"));
EXPECT_TRUE(exact(g, "Class", "[-a]"));
EXPECT_FALSE(exact(g, "Class", "["));
EXPECT_FALSE(exact(g, "Class", "[a"));
EXPECT_FALSE(exact(g, "Class", "]"));
EXPECT_FALSE(exact(g, "Class", "a]"));
EXPECT_TRUE(exact(g, "Class", u8"[あ-ん]"));
EXPECT_FALSE(exact(g, "Class", u8"あ-ん"));
EXPECT_TRUE(exact(g, "Class", "[-+]"));
EXPECT_TRUE(exact(g, "Class", "[+-]"));
EXPECT_TRUE(exact(g, "Class", "[\\^]"));
}
TEST(LeftRecursiveTest, PEG_Negated_Class) {
auto g = ParserGenerator::grammar();
EXPECT_FALSE(exact(g, "NegatedClass", "[^]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^a]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^a-z]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^az]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^a-zA-Z-]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^a-zA-Z-0-9]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^a-]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^-a]"));
EXPECT_FALSE(exact(g, "NegatedClass", "[^"));
EXPECT_FALSE(exact(g, "NegatedClass", "[^a"));
EXPECT_FALSE(exact(g, "NegatedClass", "^]"));
EXPECT_FALSE(exact(g, "NegatedClass", "^a]"));
EXPECT_TRUE(exact(g, "NegatedClass", u8"[^あ-ん]"));
EXPECT_FALSE(exact(g, "NegatedClass", u8"^あ-ん"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^-+]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^+-]"));
EXPECT_TRUE(exact(g, "NegatedClass", "[^^]"));
}
TEST(LeftRecursiveTest, PEG_Range) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Range", "a"));
EXPECT_TRUE(exact(g, "Range", "a-z"));
EXPECT_FALSE(exact(g, "Range", "az"));
EXPECT_FALSE(exact(g, "Range", ""));
EXPECT_FALSE(exact(g, "Range", "a-"));
EXPECT_FALSE(exact(g, "Range", "-a"));
}
TEST(LeftRecursiveTest, PEG_Char) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Char", "\\f"));
EXPECT_TRUE(exact(g, "Char", "\\n"));
EXPECT_TRUE(exact(g, "Char", "\\r"));
EXPECT_TRUE(exact(g, "Char", "\\t"));
EXPECT_TRUE(exact(g, "Char", "\\v"));
EXPECT_TRUE(exact(g, "Char", "\\'"));
EXPECT_TRUE(exact(g, "Char", "\\\""));
EXPECT_TRUE(exact(g, "Char", "\\["));
EXPECT_TRUE(exact(g, "Char", "\\]"));
EXPECT_TRUE(exact(g, "Char", "\\\\"));
EXPECT_TRUE(exact(g, "Char", "\\000"));
EXPECT_TRUE(exact(g, "Char", "\\377"));
EXPECT_FALSE(exact(g, "Char", "\\477"));
EXPECT_FALSE(exact(g, "Char", "\\087"));
EXPECT_FALSE(exact(g, "Char", "\\079"));
EXPECT_TRUE(exact(g, "Char", "\\00"));
EXPECT_TRUE(exact(g, "Char", "\\77"));
EXPECT_FALSE(exact(g, "Char", "\\80"));
EXPECT_FALSE(exact(g, "Char", "\\08"));
EXPECT_TRUE(exact(g, "Char", "\\0"));
EXPECT_TRUE(exact(g, "Char", "\\7"));
EXPECT_FALSE(exact(g, "Char", "\\8"));
EXPECT_TRUE(exact(g, "Char", "\\x0"));
EXPECT_TRUE(exact(g, "Char", "\\x00"));
EXPECT_FALSE(exact(g, "Char", "\\x000"));
EXPECT_TRUE(exact(g, "Char", "\\xa"));
EXPECT_TRUE(exact(g, "Char", "\\xab"));
EXPECT_FALSE(exact(g, "Char", "\\xabc"));
EXPECT_TRUE(exact(g, "Char", "\\xA"));
EXPECT_TRUE(exact(g, "Char", "\\xAb"));
EXPECT_FALSE(exact(g, "Char", "\\xAbc"));
EXPECT_FALSE(exact(g, "Char", "\\xg"));
EXPECT_FALSE(exact(g, "Char", "\\xga"));
EXPECT_FALSE(exact(g, "Char", "\\u0"));
EXPECT_FALSE(exact(g, "Char", "\\u00"));
EXPECT_TRUE(exact(g, "Char", "\\u0000"));
EXPECT_TRUE(exact(g, "Char", "\\u000000"));
EXPECT_FALSE(exact(g, "Char", "\\u0000000"));
EXPECT_TRUE(exact(g, "Char", "\\uFFFF"));
EXPECT_TRUE(exact(g, "Char", "\\u10000"));
EXPECT_TRUE(exact(g, "Char", "\\u10FFFF"));
EXPECT_FALSE(exact(g, "Char", "\\u110000"));
EXPECT_FALSE(exact(g, "Char", "\\uFFFFFF"));
EXPECT_TRUE(exact(g, "Char", "a"));
EXPECT_TRUE(exact(g, "Char", "."));
EXPECT_TRUE(exact(g, "Char", "0"));
EXPECT_FALSE(exact(g, "Char", "\\"));
EXPECT_TRUE(exact(g, "Char", " "));
EXPECT_FALSE(exact(g, "Char", " "));
EXPECT_FALSE(exact(g, "Char", ""));
EXPECT_TRUE(exact(g, "Char", u8""));
}
TEST(LeftRecursiveTest, PEG_Operators) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "LEFTARROW", "<-"));
EXPECT_TRUE(exact(g, "SLASH", "/ "));
EXPECT_TRUE(exact(g, "AND", "& "));
EXPECT_TRUE(exact(g, "NOT", "! "));
EXPECT_TRUE(exact(g, "QUESTION", "? "));
EXPECT_TRUE(exact(g, "STAR", "* "));
EXPECT_TRUE(exact(g, "PLUS", "+ "));
EXPECT_TRUE(exact(g, "OPEN", "( "));
EXPECT_TRUE(exact(g, "CLOSE", ") "));
EXPECT_TRUE(exact(g, "DOT", ". "));
}
TEST(LeftRecursiveTest, PEG_Comment) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Comment", "# Comment.\n"));
EXPECT_FALSE(exact(g, "Comment", "# Comment."));
EXPECT_FALSE(exact(g, "Comment", " "));
EXPECT_FALSE(exact(g, "Comment", "a"));
}
TEST(LeftRecursiveTest, PEG_Space) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "Space", " "));
EXPECT_TRUE(exact(g, "Space", "\t"));
EXPECT_TRUE(exact(g, "Space", "\n"));
EXPECT_FALSE(exact(g, "Space", ""));
EXPECT_FALSE(exact(g, "Space", "a"));
}
TEST(LeftRecursiveTest, PEG_EndOfLine) {
auto g = ParserGenerator::grammar();
EXPECT_TRUE(exact(g, "EndOfLine", "\r\n"));
EXPECT_TRUE(exact(g, "EndOfLine", "\n"));
EXPECT_TRUE(exact(g, "EndOfLine", "\r"));
EXPECT_FALSE(exact(g, "EndOfLine", " "));
EXPECT_FALSE(exact(g, "EndOfLine", ""));
EXPECT_FALSE(exact(g, "EndOfLine", "a"));
}
TEST(LeftRecursiveTest, PEG_EndOfFile) {
Grammar g = make_peg_grammar();
EXPECT_TRUE(exact(g, "EndOfFile", ""));
EXPECT_FALSE(exact(g, "EndOfFile", " "));
}