2011-01-26 5 views
2

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

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

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

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

EDIT: Хорошо у меня очень простой грамматики:

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, но я не понимаю, как структурировать свои шаблоны. В частности, какой шаблон идет в грамматике. Можете ли вы помочь мне на коротком примере?

+0

Какие грамматики вы имеете в виду именно? Можете ли вы опубликовать их (или разместить ссылку на них, если они большие)? Почему вы не можете генерировать лексер и парсер? Вы получаете сообщения об ошибках? Если да, можете ли вы опубликовать их? –

+0

Барт, я добавил некоторые подробности. – Dan

+2

Есть ли конкретная причина, по которой вы сами создаете парсер? Почему бы не использовать [существующий парсер] (http://www.mediawiki.org/wiki/Alternative_parsers) вместо этого? –

ответ

5

Хорошо, после вашего EDIT у меня есть несколько рекомендаций.

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

Об испускании HTML-кода, «правильный» способ сделать это действительно с помощью StringTemplate, но учитывая тот факт, что вы довольно новичок в ANTLR, я бы сохранил все просто. Вы можете создать атрибут StringBuilder в классе parser, который будет собирать весь ваш 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 

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

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

+0

Большое спасибо, ваши комментарии действительно полезны! – Dan

+0

@ Дэн, пожалуйста. –