Написание шаблона языка / VewEngine - PullRequest
0 голосов
/ 01 мая 2009

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

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

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

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

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

Если бы вы были на моем месте и не были знатоком языка, с чего бы вам начать?

Ответы [ 4 ]

3 голосов
/ 10 мая 2009

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

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

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

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

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

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

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

0 голосов
/ 28 мая 2009

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

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

0 голосов
/ 28 мая 2009

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

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

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

0 голосов
/ 02 мая 2009

Шаг 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): используйте подстановку regexp, чтобы преобразовать шаблон в eval () -подобную строку в язык хоста и запустите eval (), чтобы создать экземпляр шаблона.

...