ANTLR-разрешить любой символ между ключевыми словами to



Я хотел бы определить грамматику для простого языка.



Язык допускает некоторые виды назначений.



Пример



keyworda: this is the 1 keyword-A
keywordb: this is the second keywordb
...


Дело в том, что после ключевого слова и ':' любой символ должен быть возможен (ключевое слово тоже)



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



Моя последняя идея провалилась:



rule 
: 'keyworda' ':' anychar* 'keywordb' ':' anychar* EOF
;

anychar
: .
;

NEWLINE
: ('r'? 'n') {$channel=HIDDEN;}
;


Править



Прежде всего: спасибо за ваш ответ!



Я прочитал инструкцию. и посмотрел учебники Скотта стенчфилда.



Проблема в том, что я не понимаю, что такое "anychar"!



Вы правы, грамматика, которую я написал выше, была неправильной, потому что я торопился.

Лучшая попытка-это вперед. Проблема еще в том, что токенизатор распознает, например, keyworda в определении ala



keyworda : this is keyworda.
keywordb : this is another key!
...


Грамматика:



rule
: KEYA ':' STRING_LITERAL* NEWLINE
keybdefinition*
EOF
;

keybdefinition
: KEYB ':' STRING_LITERAL* NEWLINE
;


KEYA: 'keyworda';
KEYB:'keywordb';
STRING_LITERAL: 'a'..'z' | 'A'..'Z' | '0'..'9' | ':' | '.' | '&' | '/' | '\' | ';';

NEWLINE: 'r'? | 'n';
SPACE: (' ' | 't') {$channel=HIDDEN;};


ПРАВКА II



О боже, это же совершенно очевидно-делать все так, как ты объяснил. Не знаю, почему я сам этого не сделал! Большое спасибо Тиму за Ваше объяснение!

У меня остался еще один вопрос.:
Если я определяю свои лексемы для лексера и свою грамматику для синтаксического анализатора. Является ли это распространенным способом проверки семантики в древовидном синтаксическом анализаторе или в самом синтаксическом анализаторе?



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



keyworda : ab
keywordb : xy
keyworda : ab1
keywordb : xy1
...


Теперь я хочу проверить, если после каждого определения keyworda определена keywordb.
Позже я хочу проверить, правильно ли значение, если значение правильно.
Предположим, что у нас есть ключевое слово extends : 'keyword value', и мне нужно проверить, определено ли уже 'keyword value'.



Я мог бы сделать это двумя способами: Во-первых, изменить грамматическое правило для парсера и добавить java-код для проверки прямо там. Во-вторых, грамматика остается такой, какая она есть, и я определяю древовидный синтаксический анализатор grammer для проверки этих условий.

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

Большое Спасибо за вашу помощь

508   1  

1 ответ:

. имеет различное значение внутри правил лексера и парсера. Внутри правил лексера он соответствует любому символу из диапазона \u000...\uFFFF. А внутри правил парсера . соответствует любому токену.

Обратите внимание, что правила лексера начинаются с заглавной буквы, а правила синтаксического анализа-со строчной буквы. Вы также можете создавать токены (правила лексера) как литералы внутри правил синтаксического анализа. Это означает, что ваша грамматика создаст только 4 различных лексемы (на самом деле 3, так как NEWLINE "скрытый"):
  • 'keyworda'
  • ':'
  • 'keywordb'
  • NEWLINE (который удаляется из потока токенов по умолчанию)

(EOF является встроенным токеном)

Итак, это делает ваше правило anychar соответствующим либо 'keyworda', ':' или 'keywordb', а не любой символ, как можно было бы ожидать.

Кроме того, кажется, что вы отделяете свой key ':' value-записи по разрывам строк, но вы удаляете разрывы строк во время фазы лексирования. Около удаляя их, как вы должны знать, что такое конец value и что такое начало key? Ваш токен-поток будет одним непрерывным потоком ключевых слов , любые символы идвоеточия , поэтому невозможно определить, когда ключевое слово действительно является ключевым словом или частью value (справа от ':'). Для этого вам нужен маркер разрыва строки.

Похоже, что вы начали использовать ANTLR, на самом деле не зная, что вы делаете: IMO, это не способ изучите этот конкретный инструмент. Я рекомендую получить копиюокончательной ссылки ANTLR или прочитать/посмотреть некоторыеучебники ANTLR , прежде чем продолжить.

Удачи вам!

EDIT

Вот краткая демонстрация того, как ключевое слово также может быть частью вашего "значения":

Файл: T. g

grammar T;

parse
  :  line+ EOF
  ;

line
  :  key COLON value eol 
     {System.out.printf("key='\%s', value='\%s'\n", $key.text, $value.text);}
  ;

value
  :  any_except_newline*
  ;

key
  :  KEYA
  |  KEYB
  ;

any_except_newline
  :  COLON
  |  KEYA
  |  KEYB
  |  WORD
  |  ANYCHAR
  ;

eol
  :  NEWLINE
  |  EOF
  ;

COLON   : ':';
KEYA    : 'keyworda';
KEYB    : 'keywordb';
WORD    : ('a'..'z' | 'A'..'Z')+;
NEWLINE : '\r'? '\n' | '\r';
SPACE   : (' ' | '\t') {$channel=HIDDEN;};
ANYCHAR : .; 

Файл: Main.java

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    String source = 
        "keyworda : this is keyworda.\n" + 
        "keywordb : this is another key!";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

Если вы теперь запустите демонстрацию, сделав:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

Вы бы проследили, чтобы следующее было напечатано в консоль:

key='keyworda', value='this is keyworda.'
key='keywordb', value='this is another key!'

Comments

    Ничего не найдено.