Antlr3 .Net, как построить простую грамматику - PullRequest
1 голос
/ 08 марта 2012

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

Foo.Bar.Blah(Mom.Dad, Son.Daughter(Frank.Bob), Dog)

По сути, это рекурсивно. Я пойму это.

Я полностью в лесу с этим. Не уверен, как начать. То, что я построил в настоящее время, что на самом деле не работает, это:

tree grammar XmlTypeName;

options {
    language=CSharp2;
}

RPAREN
  : '('
  ;

LPAREN
  : ')'
  ;

SEP
  : ','
  ;

TYPE  
  : ('a'..'z'|'A'..'Z'|'0'..'9'|'_')+
  ;

prog
  : type;

type
  : TYPE (RPAREN type (SEP type)? LPAREN)? (EOF)?
  ;

Это даже близко не подходит к работе. Antlr3.exe выдает ошибки о том, что RPARAM и LPARAM не разрешены в синтаксическом анализаторе дерева. Парсер деревьев - это даже то, что мне нужно?

Я хотел бы создать простой AST, который позволит мне перемещаться по типам.

1 Ответ

2 голосов
/ 08 марта 2012

Нет, вы не должны использовать древовидную грамматику.Древовидная грамматика используется после , когда парсер создал AST.Просто удалите из него ключевое слово tree.

Несколько других замечаний:

  • вы хотите сопоставить один или несколько разделенных запятыми type s внутри скобок, но вы использовалиtype (SEP type)?, что соответствует одному или двум type с.Вместо этого вам понадобится type (SEP type)*;
  • вы не учитываете . внутри type s;
  • вы должны отбрасывать буквальные пробелы в лексере.

Нечто подобное поможет, скорее всего:

grammar XmlTypeName;

options {
  language=CSharp2;
}

prog
 : type EOF
 ;

type
 : name (RPAREN type (SEP type)* LPAREN)? 
 ;

name
 : ID (DOT ID)*
 ;

RPAREN
 : '('
 ;

LPAREN
 : ')'
 ;

SEP
 : ','
 ;

DOT
 : '.'
 ;

ID  
 : ('a'..'z'|'A'..'Z'|'0'..'9'|'_')+
 ;

SPACE
 : (' '|'\t')+ {Skip();} // if 'Skip()' doesn't work, try 'skip()'
 ;

Однако вышеприведенное просто создает плоский список токенов.Если вы хотите создать правильный AST, вам нужно «сообщить» ANTLR, какие узлы / токены являются корневыми токенами, а какие отбрасывать (например, запятая, скобка, ...).

grammar XmlTypeName;

options {
  output=AST;
  language=CSharp2;
}

tokens {
  TYPE;
  NAME;
}

prog
 : type EOF -> type
 ;

type
 : name (RPAREN type (SEP type)* LPAREN)? -> ^(TYPE name type*)
 ;

name
 : ID (DOT ID)* -> ^(NAME ID+)
 ;

RPAREN
 : '('
 ;

LPAREN
 : ')'
 ;

SEP
 : ','
 ;

DOT
 : '.'
 ;

ID  
 : ('a'..'z'|'A'..'Z'|'0'..'9'|'_')+
 ;

SPACE
 : (' '|'\t')+ {skip();}
 ;

который создает следующий AST:

enter image description here

Подробнее о создании AST с помощью ANTLR: Как вывести AST, построенный с использованием ANTLR?

...