Как интерпретировать псевдокод в C#?
У меня есть алгоритм интерпретации данных и фактические данные. Используя этот алгоритм, я должен интерпретировать фактические данные и отображать их в виде отчета.
Для этого, во-первых, мне нужно создать форму, которая будет принимать некоторые значения переменных от пользователя. Переменные определены в псевдокоде, как показано ниже. (приведен один пример)
AGEYEARS {
Description: Age in Years
Type: Range;
MinVal: 0;
MaxVal: 124;
Default: 0;
ErrorAction: ERT1:=04 GRT4:=960Z;
}
У меня есть несколько переменных, как это в моем файле Variables.txt. Я не хочу использовать StreamReader, читать его построчно и интерпретировать переменные.
Вместо этого я ищу некоторую логику, которая может читать XXXX { } как один объект и Type:Range as Attribute:Value. Таким образом, я могу пропустить один шаг чтения файла и преобразования его в понятный код.
Таким образом, у меня также есть другие файлы, которые имеют условия для проверки. Например, ЕСЛИ СЕКС = '9', ТО СЕКС:=U ENDIF
Есть ли способ интерпретировать их легко и быстрее? Может ли кто-нибудь помочь мне с этим?
Я использую C# в качестве языка программирования.
2 ответа
Так что вам нужен парсер для DSL.
Я могу посоветовать вам ANTLR, который позволит вам легко построить грамматику.
Вот совершенно непроверенная простая грамматика для этого:
grammar ConfigFile;
file: object+;
object: ID '{' property+ '}';
property: ID ':' value ';';
value: (ID|CHAR)+;
ID: [a-zA-Z][a-zA-Z0-9_]*;
WS: [ \t\r\n]+ -> channel(HIDDEN);
CHAR: .;
Альтернативное решение: вы также можете использовать регулярные выражения:
(?<id>\w+)\s*\{\s*(?:(?<prop>\w+)\s*:\s*(?<value>.+?)\s*;\s*)*\}
Затем извлеките захваченную информацию. Для каждого матча у вас будет группа id
с названием объекта. Группы prop
а также value
будет иметь несколько захватов, каждая пара определяет свойство.
В C#:
var text = @"
AGEYEARS {
Description: Age in Years;
Type: Range;
MinVal: 0;
MaxVal: 124;
Default: 0;
ErrorAction: ERT1:=04 GRT4:=960Z;
}
OTHER {
Foo: Bar;
Bar: Baz;
}";
var re = new Regex(@"(?<id>\w+)\s*\{\s*(?:(?<prop>\w+)\s*:\s*(?<value>.+?)\s*;\s*)*\}");
foreach (Match match in re.Matches(text))
{
Console.WriteLine("Object {0}:", match.Groups["id"].Value);
var properties = match.Groups["prop"].Captures.Cast<Capture>();
var values = match.Groups["value"].Captures.Cast<Capture>();
foreach (var property in properties.Zip(values, (prop, value) => new {name = prop.Value, value = value.Value}))
{
Console.WriteLine(" {0} = {1}", property.name, property.value);
}
Console.WriteLine();
}
Это решение не так "красиво", как парсер, но работает без какой-либо внешней библиотеки.
Я советую вам не использовать регулярные выражения. Возможно, это сработает при запуске, но если ваша задача станет немного сложнее, возможно, регулярное выражение не решит вашу проблему, потому что технически не может этого сделать.
Лучший выбор (по цене добавления библиотеки) - использовать какой-то парсер. Для C# их может быть не так много, как для других языков, но их достаточно - просто выберите:-). У вас есть ирония, Coco / R, GOLD, ANTLR, LLLPG, Sprache или мой NLT.
Если вы чувствуете, что у вас будут проблемы с математическим приоритетом (т.е. вам придется работать с оценкой выражений типа "5+5*2", которые должны давать 15, а не 20), чем сравнивать анализаторы сверху вниз - ANLTR является одним из них - синтаксис первый против анализаторов снизу вверх - NLT, например. Обычно в первых вы должны писать правила в причудливом порядке (вы должны встраивать правила), а во вторых вы должны просто установить их порядок (указав *
идет раньше +
). Другими словами, правила отделены от приоритета.