Parse index name - lenient parser that accepts various token types for better error messages This allows invalid names to be parsed so we can provide meaningful validation errors
(tokens: &[Token])
| 4774 | /// Parse index name - lenient parser that accepts various token types for better error messages |
| 4775 | /// This allows invalid names to be parsed so we can provide meaningful validation errors |
| 4776 | fn parse_index_name(tokens: &[Token]) -> IResult<&[Token], String> { |
| 4777 | if let Some(token) = tokens.first() { |
| 4778 | let name = match token { |
| 4779 | // Valid identifier tokens |
| 4780 | Token::Identifier(s) => Some(s.clone()), |
| 4781 | Token::String(s) => Some(s.clone()), |
| 4782 | |
| 4783 | // Accept integers so we can validate "cannot start with digit" later |
| 4784 | Token::Integer(n) => Some(n.to_string()), |
| 4785 | Token::Float(f) => Some(f.to_string()), |
| 4786 | |
| 4787 | // Accept keywords that might be used as identifiers |
| 4788 | Token::Value => Some("value".to_string()), |
| 4789 | Token::Type => Some("type".to_string()), |
| 4790 | Token::User => Some("user".to_string()), |
| 4791 | Token::Role => Some("role".to_string()), |
| 4792 | Token::Schema => Some("schema".to_string()), |
| 4793 | Token::Data => Some("data".to_string()), |
| 4794 | Token::Graph => Some("graph".to_string()), |
| 4795 | Token::Node => Some("node".to_string()), |
| 4796 | Token::Edge => Some("edge".to_string()), |
| 4797 | Token::Path => Some("path".to_string()), |
| 4798 | Token::Table => Some("table".to_string()), |
| 4799 | Token::Property => Some("property".to_string()), |
| 4800 | |
| 4801 | _ => None, |
| 4802 | }; |
| 4803 | |
| 4804 | if let Some(mut name_str) = name { |
| 4805 | let mut remaining = &tokens[1..]; |
| 4806 | |
| 4807 | // Check if next token is a minus sign followed by identifier (e.g., "invalid-name") |
| 4808 | // Consume the pattern to give better error message later |
| 4809 | while let Some(Token::Minus) = remaining.first() { |
| 4810 | if let Some(Token::Identifier(suffix)) = remaining.get(1) { |
| 4811 | name_str.push('-'); |
| 4812 | name_str.push_str(suffix); |
| 4813 | remaining = &remaining[2..]; |
| 4814 | } else { |
| 4815 | break; |
| 4816 | } |
| 4817 | } |
| 4818 | |
| 4819 | // Check if this was an integer followed by underscore and identifier (e.g., "123_invalid") |
| 4820 | // This handles the case where lexer splits it as: Integer(123), Identifier("_invalid") |
| 4821 | if let Token::Integer(_) = token { |
| 4822 | while let Some(Token::Identifier(suffix)) = remaining.first() { |
| 4823 | if suffix.starts_with('_') { |
| 4824 | name_str.push_str(suffix); |
| 4825 | remaining = &remaining[1..]; |
| 4826 | } else { |
| 4827 | break; |
| 4828 | } |
| 4829 | } |
| 4830 | } |
| 4831 | |
| 4832 | return Ok((remaining, name_str)); |
| 4833 | } |
no test coverage detected