Вопрос

Помимо выполнения какой-либо реальной работы, у меня есть зуд.Мне не терпится написать механизм просмотра, который точно имитирует систему шаблонов с другого языка (Template Toolkit / Perl).Это один из тех проектов, если бы у меня было время / сделать это, чтобы изучить что-то новое.

Я потратил время, просматривая CoCo / R и ANTLR, и, честно говоря, у меня от этого болит голова, но кое-что из CoCo / R запоминается.К сожалению, большинство примеров посвящено созданию компилятора, который считывает исходный код, но, похоже, ни один из них не описывает, как создать процессор для шаблонов.

Да, это одно и то же, но я не могу понять, как определить язык для шаблонов, где большая часть исходного кода - это html, а не фактический анализируемый и запускаемый код.

Есть ли какие-нибудь хорошие ресурсы для начинающих для подобных вещей?Я взял ganer в Spark, у которого, похоже, не было грамматики в репозитории.

Возможно, это излишне, и можно было бы просто протестировать-заменить синтаксис шаблона на c # в файле и скомпилировать его. http://msdn.microsoft.com/en-us/magazine/cc136756.aspx#S2

Если бы вы были на моем месте и не были экспертом по созданию языков, с чего бы вы начали?

Это было полезно?

Решение

Грамматика Spark реализована с использованием свободно ориентированного на предмет языка.

Он объявлен в нескольких слоях. Правила, которые распознают синтаксис html, объявлены в MarkupGrammar.cs - они основаны на грамматических правилах, скопированных непосредственно из спецификации xml.

Правила разметки относятся к ограниченному подмножеству правил синтаксиса csharp, объявленных в CodeGrammar.cs - это подмножество, потому что Spark нужно только распознать достаточно csharp, чтобы настроить одинарные кавычки вокруг строк в двойные кавычки, сопоставить фигурные скобки и т. д.

Сами отдельные правила имеют тип ParseAction < !> л; TValue <> GT!; делегат , который принимает должность и верните ParseResult . ParseResult - это простой класс, который содержит элемент данных TValue, проанализированный действием, и новый экземпляр Position, который был продвинут после содержимого, которое произвело TValue.

Это само по себе не очень полезно, пока вы не введете небольшое количество операторов , как описано в грамматике синтаксического анализа выражения , которые могут комбинировать отдельные действия синтаксического анализа для создания очень подробных и надежных выражений о форме различных синтаксических конструкций.

Техника использования делегата в качестве действия разбора взята из сообщения в блоге Люка Х Монадические синтаксические анализаторы, использующие C # 3.0 . Я также написал пост о создании домена Язык синтаксического анализа .

Также можно полностью ссылаться на сборку Spark.dll и наследовать класс от базовой CharGrammar для создания совершенно новой грамматики для определенного синтаксиса. Вероятно, это самый быстрый способ начать экспериментировать с этой техникой, и пример этого можно найти в CharGrammarTester.cs .

Другие советы

Шаг 1.Используйте регулярные выражения (подстановка регулярных выражений), чтобы разделить строку вашего входного шаблона на список токенов, например, split

hel<b>lo[if foo]bar is [bar].[else]baz[end]world</b>!

Для

write('hel<b>lo')
if('foo')
write('bar is')
substitute('bar')
write('.')
else()
write('baz')
end()
write('world</b>!')

Шаг 2.Преобразуйте ваш список токенов в синтаксическое дерево:

* Sequence
** Write
*** ('hel<b>lo')
** If
*** ('foo')
*** Sequence
**** Write
***** ('bar is')
**** Substitute
***** ('bar')
**** Write
***** ('.')
*** Write
**** ('baz')
** Write
*** ('world</b>!')

class Instruction {
}
class Write : Instruction {
  string text;
}
class Substitute : Instruction {
  string varname;
}
class Sequence : Instruction {
  Instruction[] items;
}
class If : Instruction {
  string condition;
  Instruction then;
  Instruction else;
}

Шаг 3.Напишите рекурсивную функцию (называемую интерпретатором), которая может обходить ваше дерево и выполнять там инструкции.

Другой, альтернативный подход (вместо шагов 1-3), если ваш язык поддерживает eval() (например, Perl, Python, Ruby):используйте подстановку регулярного выражения, чтобы преобразовать шаблон в строку с поддержкой eval() на языке хоста, и запустите eval() для создания экземпляра шаблона.

Есть так много дел. Но это работает для простого оператора GET плюс тест. Это начало.

http://github.com/claco/tt.net/

В конце концов, у меня уже было слишком много времени в ANTLR, чтобы попробовать метод loudejs. Я хотел потратить немного больше времени на весь процесс, а не на анализатор / лексер. Возможно, в версии 2 я смогу пойти по пути Spark, когда мой мозг будет понимать вещи немного больше.

Vici Parser (ранее известный как LazyParser.NET) является открытым исходным кодом токенизатор / анализатор шаблонов / анализатор выражений, который может помочь вам начать работу.

Если это не то, что вы ищете, тогда вы можете получить некоторые идеи, посмотрев на исходный код.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top