2015-08-13 3 views
0

Мой язык имеет команды, которые могут быть параметр меньше или с параметрами, и «если» ключевое слово:Antlr4 лексер принимает неправильное правило

cmd1   // parameter-less command 
cmd2 a word // with parameter: "a word" - it starts with first non-WS char 
if cmd3   // if, not a command, followed by parameter-less command 
cmd4 if text // command with parameter: "if text" 

«если» признан if только если это первая не- WS string в строке (давайте проигнорировать комментарии на данный момент ...)

Это мои правила грамматики:грамматика TestFlow;

// Parser Rules: 
root: (lineComment | ifStat | cmd)* EOF; 

lineComment : LC; 
ifStat : IF; 
cmd : CMD; 

// Lexer Rules: 
LC : '//' ~([\n\r\u2028\u2029])* -> channel(HIDDEN); // line comment 

IF : 'if'; 

CMD : [-_a-zA-Z0-9]+ GAP LINE 
    | [-_a-zA-Z0-9]+ 
    ; 

fragment GAP : [ \t]+; 
fragment LINE : ~([\n\r\u2028\u2029])*; 

Но мой лексический определяет 3-й линии как CMD: if cmd3, а не как if следуют cmd3, как мне нужно.

Какая у меня ошибка? как это исправить?

ответ

0

Просто немного крошечные линии, сделал все идеально: в моей MyParser.g4, просто нужно было ввести:

options { tokenVocab = MyLexer; } 

сразу после parser grammar MYParser; ...

Так много времени было потрачено впустую просто найти этот маленький подробнее ...:-(


(несколько) Другие посты людей, не зная, что происходит, просто, наконец, достичь этого решения:

0

В вашем примере, как правило, не существует правила парсера, которое определяет грамматику. Это означает, что нет правила, указывающего на поиск команды «if» AND.

Что происходит в ваших словах:

Но мой лексический идентифицирует 3-ю строку как CMD: если Cmd3, а не так, как будто следует Cmd3, как мне нужно

Первый альтернативный в правило lexer CMD ищет один или несколько символов («если»), за которым следует пробел '', за которым следует LINE (cmd3). Итак, при вводе «if cmd3» он соответствует всей строке, что именно то, что вы сказали ей сделать!

Я могу рассказать вам по собственному опыту, что даже для простого языка вы узнаете лот и очень быстро, сделав шаг назад и рассмотрим некоторые примеры грамматик, что я и сделаю, если бы вы были вами теперь, чтобы избежать разочарования. I высоко рекомендую книгу об ошибках Antlr4 от www.pragprog.com, а также сайт antlr.

ОБНОВЛЕНО Я думаю, что это то, что вы можете быть заинтересованы в:

grammar myGrammar; 

root  : statement NEWLINE 
      | comment NEWLINE 
      ; 

statement : ifStat (LC)? 
      | cmdStat (LC)? 
      ; 

ifStat  : IF cmdStat; 
cmdStat  : cmd (args)*; 

cmd  : CMD; 

args  : LINE; 
CMD  : [-_a-zA-Z0-9]+ GAP LINE 
      | [-_a-zA-Z0-9]+ 
     ; 

fragment GAP : [ \t]+; 
fragment LINE : ~([\n\r\u2028\u2029])*; 
NEWLINE  : ('\r')?'\n'; 

Опять же, я должен сказать, что если вы читали книгу (что я и сделал), это может дать вам ожидаемый ответ от вашего парсера (не lexer). IfStat не является обязательным (может быть ormay быть там, на основе ваших тестовых случаев), всегда будет CMD, и после него может быть или не быть комментарий строки. Попробуйте это и посмотрите, полезно ли это. Удачи!

+0

Я изначально исключил правила парсера, как мне показалось, как вопрос лексера. В любом случае, Я обновил свой вопрос, чтобы включить правила парсера, если это поможет. Второе: правило 'IF' появляется перед' CMD', поэтому я предполагаю, что он имеет приоритет. – Tar

+0

Если вы обращаетесь к книге «Окончательный справочник ANTLR4», то у меня она есть, но это не очень хороший учебник «Начало работы». – Tar

+0

'root: ((ifStat)? Cmd (lineComment)?) * EOF;' тоже не работает. Дело в том, что 'if cmd3' появляется как один токен, как я получаю от' commonTokenStream.getTokens() '. Итак, если это единственный токен, это то, что получает парсер от lexer, он не может их разделить. Вот почему я предполагаю, что это проблема lexer, а не парсер – Tar

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