Allow most metacharacters in character classes, e.g. allow "[+-]"

Allows most metacharacters, e.g. "*+()[", to appear unescaped within a
character class.  This, along with hyphens at the end, allows "[+-]" to
match a plus or a minus.
This commit is contained in:
Charles Baker 2023-05-20 22:08:07 +12:00
parent 2235e9fe6b
commit aaea898aab
3 changed files with 43 additions and 4 deletions

View file

@ -241,7 +241,7 @@ bool RegexParser::match_item()
syntax_tree_->item_xdigit();
return true;
}
else if ( match_character() )
else if ( match_character_in_character_class() )
{
int character = escape( lexeme_begin_, lexeme_end_ );
if ( match_end_of_range() )
@ -325,7 +325,7 @@ bool RegexParser::match_negative_item()
syntax_tree_->negative_item_xdigit();
return true;
}
else if ( match_character() )
else if ( match_character_in_character_class() )
{
int character = escape( lexeme_begin_, lexeme_end_ );
if ( match_end_of_range() )
@ -344,6 +344,17 @@ bool RegexParser::match_negative_item()
bool RegexParser::match_character()
{
return match_character( "|*+?[]()-" );
}
bool RegexParser::match_character_in_character_class()
{
return match_character( "^]-" );
}
bool RegexParser::match_character( const char* metacharacters )
{
LALR_ASSERT( metacharacters );
const char* position = position_;
if ( position != end_ )
{
@ -375,7 +386,7 @@ bool RegexParser::match_character()
position_ = position;
return true;
}
else if ( !strchr("|*+?[]()-", *position) )
else if ( !strchr(metacharacters, *position) )
{
++position;
lexeme_begin_ = position_;
@ -390,7 +401,7 @@ bool RegexParser::match_character()
bool RegexParser::match_end_of_range()
{
const char* position = position_;
if ( match("-") && match_character() )
if ( match("-") && match_character_in_character_class() )
{
return true;
}

View file

@ -32,6 +32,9 @@ private:
bool match_item();
bool match_negative_item();
bool match_character();
bool match_character_in_character_class();
bool match_character( const char* metacharacters );
bool match_bracket_expression_character();
bool match_end_of_range();
bool match_identifier();
bool match( const char* lexeme );

View file

@ -1378,4 +1378,29 @@ SUITE( RegularExpressions )
CHECK_EQUAL( "NOT BETWEEN", lexer.lexeme() );
CHECK( lexer.symbol() == &not_between );
}
TEST( CharacterClassHyphens )
{
void* plus_or_minus;
RegexCompiler compiler;
compiler.compile( "[+-]", &plus_or_minus );
Lexer<const char*> lexer( compiler.state_machine() );
const char* regex = "+";
lexer.reset( regex, regex + strlen(regex) );
lexer.advance();
CHECK( lexer.symbol() == &plus_or_minus );
CHECK( lexer.lexeme() == "+" );
lexer.advance();
CHECK( lexer.symbol() == nullptr );
regex = "-";
lexer.reset( regex, regex + strlen(regex) );
lexer.advance();
CHECK( lexer.symbol() == &plus_or_minus );
CHECK( lexer.lexeme() == "-" );
lexer.advance();
CHECK( lexer.symbol() == nullptr );
}
}