Регулярное выражение для соответствия действительному имени пространства имен
Я думал, что этот вопрос задавался ранее, но я попробовал Google, но не нашел ответа. Возможно, я использовал неправильные ключевые слова.
Можно ли использовать регулярное выражение для соответствия действительному имени пространства имен C#?
Обновить:
Спасибо всем за ваши ответы и исследования! Этот вопрос гораздо сложнее, чем я ожидал. Как отмечали Oscar Mederos и Joey, допустимое пространство имен не может содержать зарезервированные ключевые слова C# и может содержать гораздо больше символов Юникода, чем латинские буквы.
Но мой текущий проект должен только синтаксически проверять пространства имен. Таким образом, я принял primfaktor, но я проголосовал за все ответы.
4 ответа
Для меня это сработало:
^using (@?[a-z_A-Z]\w+(?:\.@?[a-z_A-Z]\w+)*);$
Он сопоставляет использование строк в C# и возвращает полное пространство имен в первой (и единственной) группе совпадений. Вы можете удалить ^
а также $
учитывать отступы и конечные комментарии.
Пример на RegExr.
Я знаю, что вопрос заключался в том, как проверить пространство имен с помощью регулярных выражений, но другой способ сделать это - заставить компилятор выполнять свою работу. Я не уверен, что то, что у меня есть, улавливает 100% всех ошибок, это работает довольно хорошо. Я создал этот ValidationRule для проекта, над которым я сейчас работаю:
using System.CodeDom.Compiler;
using System.Windows.Controls;
using Microsoft.CSharp;
using System.Text.RegularExpressions;
namespace Com.Gmail.Birklid.Ray.CodeGeneratorTemplateDialog
{
public class NamespaceValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
var input = value as string;
if (string.IsNullOrWhiteSpace(value as string))
{
return new ValidationResult(false, "A namespace must be provided.");
}
else if (this.doubleDot.IsMatch(input))
{
return new ValidationResult(false, "'..' is not valid.");
}
var inputs = (value as string).Split('.');
foreach (var item in inputs)
{
if (!this.compiler.IsValidIdentifier(item))
{
return new ValidationResult(false, string.Format(cultureInfo, "'{0}' is invalid.", item));
}
}
return ValidationResult.ValidResult;
}
private readonly CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
private readonly Regex doubleDot = new Regex("\\.\\.");
}
}
Если вы хотите узнать, может ли строка использоваться в качестве пространства имен, вам следует обратиться к Спецификациям языка C# и взглянуть на грамматику, которая проверяет пространство имен.
Пространство имен должно быть последовательностью identifiers
разделены .
, Пример:
identifier
identifier.identifier
identifier.identifier.identifier
...
И что такое identifier
?
available_identifier
или же @any_identifier
available_identifier
является any_identifier
но не может быть keyword
Зарезервировано языком.
any_identifier
является следующим:
(_|letter)(letter|number)*
Редактировать:
Я должен сказать, что это регулярное выражение может быть действительно очень сложным. Примите во внимание, что необходимо проверить, не используются ли зарезервированные ключевые слова, и вот список зарезервированных ключевых слов:
абстрактный как базовый bool прервать байт регистр поймать проверенный класс const продолжить десятичный делегат по умолчанию сделать двойное событие enum явное extern false окончательно исправил float для foreach goto, если неявный во внутреннем интерфейсе int является блокировкой длинного пространства имен новый оператор пустого объекта out переопределяет params private protected public readonly ref return sbyte загерметизированный короткий размер stackalloc статическая строковая структура переключатель
Разве вы не можете разделить валидацию, возможно, создав метод в C# или любом другом языке для его валидации вместо использования только одного регулярного выражения?
Если честно, я предлагаю вам любую из этих двух вещей:
- Реализуйте синтаксический анализатор этой грамматики (см. Ссылку). Вы можете сделать это вручную или с помощью таких инструментов, как ANTLR
Реализуйте метод, который принимает строку, которую вы хотите проверить (давайте назовем ее
str
) и напишите файл как:namespace str { class A {} }
и попробуйте скомпилировать :)
используя msbuild или любой компилятор C#. Если это дает ошибку, то вы знаете, что слово не является правильным :)