Рабочий пример wikitext-to-HTML в ANTLR 3 - PullRequest
2 голосов
/ 27 января 2011

Я пытаюсь найти переводчик wikitext-to-HTML в ANTLR 3, но я застреваю.

Вам известен рабочий пример, который я могу проверить?Я пробовал грамматику MediaWiki ANTLR и грамматику Wiki Creole, но я не могу заставить их сгенерировать лексер и парсер в ANTLR 3.

Вот ссылки на две грамматики, которые я пробовал использовать:

Я не могу заставить ни одного из этих двух сгенерировать мой Java Lexer и Parser.(Я использую ANTLR3 в качестве плагина Eclipse).MediaWiki требует много времени для сборки, а затем в какой-то момент выдает исключение OutOfMemory.В другом есть ошибки, которые я не знаю, как отлаживать.

РЕДАКТИРОВАТЬ: Хорошо, у меня есть очень базовая грамматика:

grammar wikitext;

options {
  //output = AST;
  //ASTLabelType = CommonTree;
  output = template;
  language = Java;
}

document: line (NL line?)*;

line: horizontal_line | list | heading | paragraph;

/* horizontal line */
horizontal_line: HRLINE;

/* lists */
list: unordered_list | ordered_list;

unordered_list: '*'+ content;
ordered_list: '#'+ content;

/* Headings */
heading: heading1 | heading2 | heading3 | heading4 | heading5 | heading6;
heading1: H1 plain H1;
heading2: H2 plain H2;
heading3: H3 plain H3;
heading4: H4 plain H4;
heading5: H5 plain H5;
heading6: H6 plain H6;

/* Paragraph */
paragraph: content;

content: (formatted | link)+;

/* links */
link: external_link | internal_link;

external_link: '[' external_link_uri ('|' external_link_title)? ']';
internal_link: '[[' internal_link_ref ('|' internal_link_title)? ']]' ;

external_link_uri: CHARACTER+;
external_link_title: plain;
internal_link_ref: plain;
internal_link_title: plain;

/* bold & italic */
formatted: bold_italic | bold | italic | plain;

bold_italic: BOLD_ITALIC plain BOLD_ITALIC;
bold: BOLD plain BOLD;
italic: ITALIC plain ITALIC;

/* Plain text */
plain: (CHARACTER | SPACE)+;


/**
 * LEXER RULES
 * --------------------------------------------------------------------------
 */

HRLINE: '---' '-'+;

H1: '=';
H2: '==';
H3: '===';
H4: '====';
H5: '=====';
H6: '======';

BOLD_ITALIC: '\'\'\'\'\'';
BOLD: '\'\'\'';
ITALIC: '\'\'';

NL: '\r'?'\n';

CHARACTER       :       '!' | '"' | '#' | '$' | '%' | '&'
                |       '*' | '+' | ',' | '-' | '.' | '/'
                |       ':' | ';' | '?' | '@' | '\\' | '^' | '_' | '`' | '~'
                |       '0'..'9' | 'A'..'Z' |'a'..'z' 
                |       '\u0080'..'\u7fff'
                |       '(' | ')'
                |       '\'' | '<' | '>' | '=' | '[' | ']' | '|' 
                ;

SPACE: ' ' | '\t';

Мне не совсем понятно, как поступить с выводом HTML.Я изучал StringTemplate, но я не понимаю, как структурировать мои шаблоны.В частности, какой шаблон идет в грамматике.Можете ли вы помочь мне с коротким примером?

1 Ответ

5 голосов
/ 01 февраля 2011

Хорошо, после вашего РЕДАКТИРОВАНИЯ у меня есть пара рекомендаций.

Как я уже говорил в комментариях, написание грамматики для такого языка практически невозможно. По крайней мере, пытаясь сделать это за один раз, то есть. Единственный способ увидеть эту работу - это сделать это с несколькими синтаксическими анализаторами, где первая «стадия синтаксического анализа» будет анализировать источник вики очень «грубо». Например: table будет размечен как: TABLE : '{|' .* '|}', и тогда вы создадите другой анализатор, который правильно анализирует эту таблицу. Выполнение этого в одном парсере приведет к множеству двусмысленностей в правилах парсера IMO.

Что касается выдачи HTML-кода, «правильный» способ сделать это действительно с StringTemplate, но, учитывая тот факт, что вы довольно плохо знакомы с самой ANTLR, я бы упростил задачу. Вы можете создать атрибут StringBuilder в своем классе синтаксического анализатора, который будет собирать весь ваш HTML-код при разборе исходного файла. Вы можете встроить код в правила ANTLR, заключив его в { и }.

Вот короткая демонстрация:

grammar T;

@parser::members {

  // an attribute that is only available in your 
  // parser (so only in parser rules!)
  protected StringBuilder htmlBuilder = new StringBuilder();
}

// Parser rules
parse
  :  atom+ EOF
  ;

atom
  :  header
  |  Any    {htmlBuilder.append($Any.text);} // append the text from 'Any' token
  ;

header
  :  H3 h3Content H3 {htmlBuilder.append("<h3>" + $h3Content.text + "</h3>");}
  |  H2 h2Content H2 {htmlBuilder.append("<h2>" + $h2Content.text + "</h2>");}
  |  H1 h1Content H1 {htmlBuilder.append("<h1>" + $h1Content.text + "</h1>");}
  ;

h3Content : ~H3*; // match any token except H3, zero or more times
h2Content : ~H2*; //        "               H2          "
h1Content : ~H1*; //        "               H1          "

// Lexer rules    
H3 : '===';
H2 : '==';
H1 : '=';

// Fall through rule: if non of the above 
// lexer rules matched, this one will.
Any
  :  .
  ;

Из этой грамматики вы генерируете синтаксический анализатор и лексер:

java -cp antlr-3.2.jar org.antlr.Tool T.g

, а затем создайте небольшой класс для проверки вашего синтаксического анализатора:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {

        // the source to be parsed
        String source = 
                "= header 1 =             \n"+
                "                         \n"+
                "some text here           \n"+
                "                         \n"+
                "=== header level 3 ===   \n"+
                "                         \n"+
                "and some more text         ";

        ANTLRStringStream in = new ANTLRStringStream(source);
        TLexer lexer = new TLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TParser parser = new TParser(tokens);

        // invoke the start-rule in your parser
        parser.parse();

        // print the contents of your parser's StringBuilder
        System.out.println(parser.htmlBuilder);
    }
}

и затем скомпилируйте все ваши исходные файлы:

javac -cp antlr-3.2.jar *.java

и, наконец, запустить свой основной класс

// *nix & MacOS
java -cp .:antlr-3.2.jar Main

// Windows
java -cp .;antlr-3.2.jar Main

, который выведет на консоль следующее:

<h1> header 1 </h1>             

some text here           

<h3> header level 3 </h3>   

and some more text  

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

В любом случае, что бы вы ни делали: удачи!

...