2010-01-13 4 views
4

Я занимаюсь изучением разбора языка для удовольствия ...Как создать TreeParser в ANTLR3?

Я создал грамматику ANTLR, которая, я считаю, будет соответствовать простому языку, который я надеюсь реализовать. Она будет иметь следующий синтаксис:

<FunctionName> (<OptionalArguments>+) { 
    <OptionalChildFunctions>+ 
} 

Actual Пример:

ForEach(in:[1,2,3,4,5] as:"nextNumber") { 
    Print(message:{nextNumber}) 
} 

Я считаю, у меня есть грамматика работает правильно, чтобы соответствовать этой конструкции, и теперь я attemping построить дерево абстрактного синтаксиса для язык.

Во-первых, я должен признать, что я не совсем уверен, КАК это дерево должно выглядеть. Во-вторых, у меня полная потеря, как это сделать в моей грамматике Antlr ... Я пробовал без особых успехов часами.

Это настоящая идея, с которой я иду, для дерева - пожалуйста, со мной! :)

    FunctionName 
       /  \ 
      Attributes   \ 
      /\  /\ 
      ID /\ ChildFunctions 
     /\ ID etc 
     / \ 
    Attribute AttributeValue 
     Type 

Это мой текущий Antlr файл грамматика:

grammar Test; 

options {output=AST;ASTLabelType=CommonTree;} 

program : function ; 
function : ID (OPEN_BRACKET (attribute (COMMA? attribute)*)? CLOSE_BRACKET)? (OPEN_BRACE function* CLOSE_BRACE)?; 

attribute : ID COLON datatype; 

datatype : NUMBER | STRING | BOOLEAN | array | lookup ; 
array : OPEN_BOX (datatype (COMMA datatype)*)? CLOSE_BOX ; 
lookup : OPEN_BRACE (ID (PERIOD ID)*) CLOSE_BRACE; 

NUMBER 
: ('+' | '-')? (INTEGER | FLOAT) 
; 

STRING 
    : '"' (ESC_SEQ | ~('\\'|'"'))* '"' 
    ; 

BOOLEAN 
: 'true' | 'TRUE' | 'false' | 'FALSE' 
; 

ID : (LETTER|'_') (LETTER | INTEGER |'_')* 
    ; 

COMMENT 
    : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 
    | '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;} 
    ; 

WHITESPACE : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ; 

COLON : ':' ; 
COMMA : ',' ; 
PERIOD : '.' ; 

OPEN_BRACKET : '(' ; 
CLOSE_BRACKET : ')' ; 

OPEN_BRACE : '{' ; 
CLOSE_BRACE : '}' ; 

OPEN_BOX : '[' ; 
CLOSE_BOX : ']' ; 

fragment 
LETTER 
: 'a'..'z' | 'A'..'Z' 
; 

fragment 
INTEGER 
: '0'..'9'+ 
; 

fragment 
FLOAT 
: INTEGER+ '.' INTEGER* 
; 

fragment 
ESC_SEQ 
    : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 
    ; 

ЛЮБОЙ помощь/совет будет большой. Я пробовал читать десятки учебных пособий, и ничего о генерации АСТ, похоже, не придерживается :(

ответ

9

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

см tree construction на antlr.org сайте.

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

EDIT/Дополнительная информация:

Вот процесс, вы можете следовать, чтобы дать вам общее представление о том, как это сделать:

  1. Скачать ANTLRWorks и использовать это графический центр. Вы обязательно захотите увидеть дерево разбора и AST до и после внесения изменений. Как только вы поймете, как все работает, вы можете использовать любую IDE или редактор, который вы хотите.
  2. Существует два основных оператора для построения дерева - восклицательный знак !, который сообщает компилятору, что он не размещает узел в пределах AST, и кару ^, который сообщает ANTLR, что-то сделать корневым узлом. Начните с прохождения каждого нетерминального правила и определения того, какие элементы не должны находиться в AST. Например, вам не нужны запятые или скобки. Когда у вас есть вся информация, вы можете заполнить структуру (или создать свою собственную структуру AST), которая предоставляет всю информацию. Commas больше не помогают, поэтому добавьте ! к ним. Например:

    function: ID (OPEN_BRACKET! (attribute (COMMA!? attribute)*)? CLOSE_BRACKET!)? (OPEN_BRACE! function* CLOSE_BRACE!)?;

  3. Посмотрите на AST в ANTLRWorks до и после. Сравните.

  4. Теперь решите, какой элемент должен быть корневым узлом.Похоже, вы хотите, чтобы ID был корневым узлом, поэтому добавьте ^ после ID и сравните ANTLRWorks.

Вот несколько изменений, которые приближают ее к тому, что я думаю, что вы хотите:

program : function ; 
function : ID^ (OPEN_BRACKET! attributeList? CLOSE_BRACKET!)? (OPEN_BRACE! function* CLOSE_BRACE!)?; 
attributeList: (attribute (COMMA!? attribute)*); 
attribute : ID COLON! datatype; 
datatype : NUMBER | STRING | BOOLEAN | array | lookup ; 
array : OPEN_BOX! (datatype^ (COMMA! datatype)*)? CLOSE_BOX!; 
lookup : OPEN_BRACE! (ID (PERIOD! ID)*) CLOSE_BRACE!; 

При этом под пояс, теперь посмотрите на некоторые из tutorials.

+0

Это часть, которую я потерял, я боюсь. Я прочитал страницу по строительству деревьев и не очень понял ее :( –

+0

Спасибо за редактирование. Это добавило много полезной информации. –

+0

Действительно отличное объяснение. Я также начинаю с ANTLR, и я считаю, что сайт каким образом можно сказать, что вы купили книгу. Спасибо – INS

Смежные вопросы