Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.04.2013, 07:31   #1
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
По умолчанию Как разобрать код, аналогичный BBCode?

Имеется подзадача: разработать класс, который будет разбирать строку с тегами [size][/size], [b][b] и другие, в том числе и не стандартные, преобразовывать ее в массив байт и передавать на устройство.
В данный момент не совсем успешно осуществляю указанную операцию с помощью регулярных выражений:
Код:
	
//словарь с символами форматирования
//класс StringParserNonOverheadKeyword в своем конструкторе принимает символы начала тега, символы конца тега и символ маскирования
		protected static Dictionary<String, StringParserNonOverheadKeyword> NonOverheadDictionary=new Dictionary<String, StringParserNonOverheadKeyword>{
{"DoubleWidth", new StringParserNonOverheadKeyword("\\[doubleWidth\\]", "\\[/doubleWidth\\]", 0x09)},	 
{"Silent", new StringParserNonOverheadKeyword("\\[silent\\]", "\\[/silent\\]", 0x10)}};
		protected static List<Byte> Generate(ref String Text, Encoding DefaultEncoding, Encoding RequiredEncoding)
			{
				List<Byte> returnedValue;
				String[] startOfKeywordSplitResult;
				String[] endOfKeywordSplitResult;
				String processingString;
			
				returnedValue=new List<Byte>();
				processingString=Text;

				
			
				foreach(KeyValuePair<String, StringParserNonOverheadKeyword> currentNode in NonOverheadDictionary)
				{
					if(Regex.IsMatch(processingString, currentNode.Value.StartOfKeyword)==true)
					{						startOfKeywordSplitResult=Regex.Split(processingString, currentNode.Value.StartOfKeyword);
					
						for(Int32 i=0;i!=startOfKeywordSplitResult.Length;i++)
						{
							Console.WriteLine("Результаты Split: {0}", startOfKeywordSplitResult[i]);
							if(startOfKeywordSplitResult[i]!=String.Empty)
							{
								if(Regex.IsMatch(startOfKeywordSplitResult[i], currentNode.Value.EndOfKeyword))
								{
									//проверяем соответствие количества тегов закрытия
									if(Regex.Matches(startOfKeywordSplitResult[i], currentNode.Value.EndOfKeyword).Count>1)
									{
										throw new ArgumentException("Несоответствие порядка тегов открытия и закрытия в строке");
									}
									else
									{																
										//если количество вхождений тега закрытия не превышает 1, то в результате нижеследующего Split получим массив из двух элементов
											endOfKeywordSplitResult=Regex.Split(startOfKeywordSplitResult[i], currentNode.Value.EndOfKeyword);
										//рекурсивно вызовем текущий метод, чтобы распарсить все байты				
												List<Byte> res1=Generate(ref endOfKeywordSplitResult[0], DefaultEncoding, RequiredEncoding);
												List<Byte> res2=Generate(ref endOfKeywordSplitResult[1], DefaultEncoding, RequiredEncoding);
										//маскируем каждый из символов
											foreach(Byte res1Byte in res1)
											{
												returnedValue.Add(currentNode.Value.ByteForFormatting);
												returnedValue.Add(res1Byte);
											}
											returnedValue.AddRange(res2);											
									}

									//удалить вхождение
										//endOfKeywordSplitResult[i]=String.Empty;
										endOfKeywordSplitResult[0]=String.Empty;
										processingString=String.Join(String.Empty, endOfKeywordSplitResult);
										Text = processingString;
								}
								else
								{
									if(i==0)
									{
										Boolean isFinded=false;
										//returnedValue.AddRange(Encoding.Convert(DefaultEncoding, RequiredEncoding, DefaultEncoding.GetBytes(startOfKeywordSplitResult[i])));
										foreach(KeyValuePair<String, StringParserNonOverheadKeyword> currentNode2 in NonOverheadDictionary)
										{
											if(Regex.IsMatch(startOfKeywordSplitResult[i], currentNode2.Value.StartOfKeyword)==true)
											{
												isFinded=true;
												returnedValue.AddRange(Generate(ref startOfKeywordSplitResult[i], DefaultEncoding, RequiredEncoding));
												break;
											}
										}
										if(isFinded==false)
										{
											returnedValue.AddRange(Encoding.Convert(DefaultEncoding, RequiredEncoding, DefaultEncoding.GetBytes(startOfKeywordSplitResult[i])));
										}
									}
									else
									{
										throw new ArgumentException("Невозможно найти тег закрытия форматирования в строке");
									}
								}
							}
					
						}
					}
				}
			
				//добавляем оставшиеся символы
				returnedValue.AddRange(Encoding.Convert(DefaultEncoding, RequiredEncoding, DefaultEncoding.GetBytes(processingString)));
				processingString=String.Empty;
				Text=processingString;
			
				return returnedValue;
			}
Продолжение в следующем посте
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.

Последний раз редактировалось Mixim; 24.04.2013 в 07:34.
Mixim вне форума Ответить с цитированием
Старый 24.04.2013, 07:32   #2
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
Вопрос

Продолжение
При выполнении кода:
Код:
String str="[doubleWidth][silent]abc[/silent][/doubleWidth][doubleWidth]def[/doubleWidth]ghi[doubleWidth]jkl[/doubleWidth]";
			

			List<Byte> byteList=new List<Byte>();
			Encoding defaultEncoding=Encoding.Default;
			Encoding resultEncoding=Encoding.ASCII;
			
			ChangeEncodingAndMaskBytes(ref byteList, str, defaultEncoding, resultEncoding);
    	    
			Console.WriteLine("После преобразований имеем следующий список байт:");
			foreach(Byte currentNode in byteList)
			{
				Console.WriteLine(currentNode);
			}
получаем вывод ("//" - мои комментарии):
Цитата:
После преобразований имеем следующий список байт:
9
16
9//вот это не нужно
97
9
16
9//вот это не нужно
98
9
16
9//вот это не нужно
99
9
100
9
101
9
102
103
104
105
9
106
9
107
9
108
- почти то, что нужно: {16,9,97, 16,9,98, 16,9,99, 9,100, 9,101, 9,102, 103, 104, 105, 9,106, 9,107, 9,108}
Подскажите, как можно исправить указанную ситуацию? Каким образом можно реализовать универсальный метод, который не маскировал бы служебные байты?
Заранее спасибо за помощь.
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.
Mixim вне форума Ответить с цитированием
Старый 24.04.2013, 11:34   #3
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Вот набросал тут пару функций для парсинга любых кодов.
Создает список пар <Теги, текст>
Разбирает множественное тегирование и вытаскивает основной текст ...
Вроде все просто. Там уже сами подпилите под ваши нужды.
Пароль к архиву programmersforum.ru
Вложения
Тип файла: rar ConsoleApplication1.rar (23.9 Кб, 9 просмотров)
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 25.04.2013, 02:34   #4
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
По умолчанию

Цитата:
Сообщение от WorldMaster Посмотреть сообщение
Вот набросал тут пару функций для парсинга любых кодов.
Создает список пар <Теги, текст>
Разбирает множественное тегирование и вытаскивает основной текст ...
Вроде все просто. Там уже сами подпилите под ваши нужды.
Пароль к архиву programmersforum.ru
Спасибо, сейчас буду разбираться. Пока что заметил небольшую некорректность в Вашем коде: теги ищуться по ключевому символу '[', вместо заранее заданных ключевых слов, но это не сложно исправить
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.

Последний раз редактировалось Mixim; 25.04.2013 в 02:43.
Mixim вне форума Ответить с цитированием
Старый 25.04.2013, 06:56   #5
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Цитата:
Сообщение от Mixim Посмотреть сообщение
Спасибо, сейчас буду разбираться. Пока что заметил небольшую некорректность в Вашем коде: теги ищуться по ключевому символу '[', вместо заранее заданных ключевых слов, но это не сложно исправить
После обработки функцией у вас будет список слов с тегами ... проще его потом обрабатывать. Я на то у делал упор.
Можно немного переработать структуру результирующую, класс придумать в котором будет хранится текст и наложенные на него теги.

В моем же случае функция выполняет разбор для тэгов с любым названием как раз чтобы не затачивать ее под конкретный набор тэгов.
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 25.04.2013, 09:19   #6
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
По умолчанию

Цитата:
Сообщение от WorldMaster Посмотреть сообщение
После обработки функцией у вас будет список слов с тегами ... проще его потом обрабатывать. Я на то у делал упор.
Можно немного переработать структуру результирующую, класс придумать в котором будет хранится текст и наложенные на него теги.

В моем же случае функция выполняет разбор для тэгов с любым названием как раз чтобы не затачивать ее под конкретный набор тэгов.
Еще раз спасибо. Примененная универсальность разбора дает неприятную проблему: если теги идут в неверной последовательности (сначала тег закрытия, а потом открытия), то приложение успешно съедает по сути неверный формат. Немного исправил (см.вложение), теперь осталось сделать экранирование
Вложения
Тип файла: zip Console1.zip (11.0 Кб, 7 просмотров)
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.
Mixim вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Разобрать код С++ Al-chan Помощь студентам 6 24.02.2013 21:15
Нужно разобрать код на php htior PHP 5 08.12.2012 17:06
необходимо разобрать код на Си++ SashaGruffs Помощь студентам 5 08.02.2012 17:32
Как на си разобрать код программы на строки.... evgpol Помощь студентам 3 20.05.2011 23:32
Код CSS не могу разобрать... misher HTML и CSS 13 26.12.2010 21:42