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 для проверки этих условий.
Я действительно не знаю, какой путь лучше и каковы преимущества или недостатки...
Большое Спасибо за вашу помощь
1 ответ:
Обратите внимание, что правила лексера начинаются с заглавной буквы, а правила синтаксического анализа-со строчной буквы. Вы также можете создавать токены (правила лексера) как литералы внутри правил синтаксического анализа. Это означает, что ваша грамматика создаст только 4 различных лексемы (на самом деле 3, так как
.имеет различное значение внутри правил лексера и парсера. Внутри правил лексера он соответствует любому символу из диапазона\u000...\uFFFF. А внутри правил парсера.соответствует любому токену.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