test trivial {

	grammar = {
		rGrammar = "abc";
	}

	accept {abc}

	reject {ab}
	reject {bc}
	reject {abc;}
	reject {_abc}
}

test CharSet {

	grammar = {
		rGrammar = +(char_set_r("aBcD") - char_set_r("BD"));
	}

	accept {a}
	accept {aaa}
	accept {acaca}

	reject {B}
	reject {aB}
	reject {Da}
	reject {aBc}
	reject {aBcD}
}

test CharRange {

	grammar = {
		rGrammar = +(char_range_r('b', 'y') - char_range_r('e', 'h'));
	}

	accept {b}
	accept {y}
	accept {bbb}
	accept {yyy}
	accept {bcdwxy}
	accept {ybxcwd}

	reject {}
	reject {ab}
	reject {e}
	reject {h}
	reject {eh}
	reject {be}
	reject {bcdewxy}
}

test needleInHaystack {
	grammar = {
		rGrammar = *anychar_r >> alpha_r >> "=" >> alpha_r;
	}

	accept {a=a}
	accept {ba=a}
	accept {bc=ca=a}
	accept {bc=a=a}
	accept {b!a=a}
	accept {b=!a=a}

	reject {a=a;}
}

test optionalThings {
	grammar = {
		rGrammar = !( !rPart >> "-core-" >> !(+rPart >> ";") );
		rPart = +alpha_r >> !digit_r >> ".";
	}

	accept {}
	accept {-core-}
	accept {part.-core-}
	accept {part1.-core-}
	accept {-core-p.;}
	accept {p.-core-p.;}
	accept {p1.-core-p2.;}
	accept {p1.-core-p2.p.p4.;}

	reject {p1.}
	reject {p1.p2.}
	reject {p12.-core}
	reject {-core-;}
	reject {-core-p2.}
	reject {-core-p2.p3.}
	reject {-core-p2.;p3.;}
}

test CommittedEndWithAmbiguity {

	grammar = {
		rGrammar = *rPart;
		rPart = string_r("pfx") | "pfx-sfx";

		rGrammar.committed(true);
	}

	accept {}
	accept {pfx}
	accept {pfx-sfx}
	accept {pfxpfx}
	accept {pfx-sfxpfxpfx-sfxpfxpfx}

	reject {pf}
	reject {pfx.}
	reject {pfx-sf}
	reject {pfx-sfx.}
}

test leftRecursion {
	grammar = {
		rGrammar = rExpression;
		rExpression = rExpression >> "+" >> rExpression | digit_r;
	}

	accept {1}
	accept {1+2}
	accept {1+2+3}

	reject {+}
	reject {12+3}
	reject {1+2+}
	reject {+1+2}
}

test starStar {
	grammar = {
		rGrammar = *rToken;
		rToken = *rDigit;
		rDigit = digit_r;
	}

	accept {}
	accept {1}
	accept {12}
	accept {1234567890}

	reject {a}
	reject {1.2}
}

test starStarCompact {
	grammar = {
		rGrammar = *(*digit_r);
	}

	accept {}
	accept {1}
	accept {12}
	accept {1234567890}

	reject {a}
	reject {1.2}
}

test unnamed {

	grammar = {
		rGrammar = *rStatement;
		rStatement = *rInstr >> ";";
		rInstr = rName | rToken;
		rName = string_r("description");
		rToken = alpha_r >> *(alpha_r | digit_r | "_" | ".");

		rGrammar.trim(*space_r);
	}

	accept {}
	accept {;}
	accept {a;}
	accept {a b;}
	accept {a description b ; }
	
	reject {a=b;}
}

test operPrecedence {
	grammar = {
		rGrammar = rExpression;
		rExpression = rTerm >> *("+" >> rTerm);
		rTerm = rExpression >> +("*" >> rExpression) |
			digit_r;
	}

	accept {1}
	accept {1+2}
	accept {1*2}
	accept {1+2+3}
	accept {1*2*3}
	accept {1*2+3}
	accept {1+2*3}
	accept {0*1+2*3+4*5*6+7+8+9}

	reject {+}
	reject {12+3}
	reject {1+2+}
	reject {+1*2}
	reject {1+*2}
}

test selectiveTrim {
	grammar = {
		rGrammar = rNum >> rNum >> ";";
		rNum = (rFloat | rInt);
		rFloat = rInt >> "." >> rInt;
		rInt = +digit_r;

		rGrammar.trim(*space_r);
		rFloat.verbatim(true); // but rInt alone should be trimmed
		rInt.verbatim(true);

		rFloat.leaf(true);
		//rInt.leaf(true); // check trimming of verbatim non-terminals
	}

	accept {1 2;}
	accept {1.2 3;}
	accept { 1.2 3.4 ; }
	accept { 12.34 56.78 ; }

	reject {1;}
	reject {1.2;}
	reject {1. 2 3;}
	reject {1 2. 3;}
	reject {1234 57. 78;}
	reject {1 2 3;}
	reject {1 2;1}
}

test GiovanniChallenge {
	grammar = {
		rGrammar = rB >> "d";
		rB = rA >> "c" | rA >> "c" >> "c";
		rA = string_r("ab") | "abb";
	}

	accept {abcd}
	accept {abccd}
	accept {abbcd}
	accept {abbccd}

	reject {abc}
	reject {abbc}
	reject {abccc}
	reject {aabcd}
	reject {abcdd}
}

