2014-12-04 6 views
0

я следующий кусок кода:разбор отступов на основе синтаксиса (например, Python) с YECC

case 1 
of 2 
    3 
of 3 
    4 
5 

Это мой обычай токенизатор переводит к:

Tokens: [{'case',1}, 
     {integer,1,1}, 
     {eol,1}, 
     {'of',1}, 
     {integer,1,2}, 
     {block,[{integer,1,3}]}, 
     {eol,1}, 
     {'of',1}, 
     {integer,1,3}, 
     {block,[{integer,1,4}]}, 
     {eol,1}, 
     {integer,1,5}] 

Но тогда я не будучи в состоянии разобрать его следующим Yecc:

Nonterminals 
    grammar 
    statements statement 
    case_def case_conditions condition. 


Terminals 
    eol block 
    integer 
    case of. 


Rootsymbol grammar. 


grammar -> statements : '$1'. 


statements -> statement eol statements : ['$1'|'$3']. 
statements -> statement : ['$1']. 

statement -> case_def : '$1'. 
statement -> integer : '$1'. 


case_def -> 'case' integer case_conditions : ''. 

case_conditions -> case_condition case_conditions : ['$1'|'$2']. 
case_conditions -> case_condition : ['$1']. 

case_condition -> eol 'of' integer block : ''. 

Это дает мне следующий вывод:

["syntax error before: ","5"] 

Любая помощь действительно приветствуется, спасибо.

ответ

1

Я думаю, что в бессрочном списке у вас должно быть case_condition вместо condition.

Ваш пользовательский сканер игнорирует отступ. Он должен излучать токены для INDENT и DEDENT. Я нашел example in yacc. Затем вы можете изменить свою грамматику, чтобы использовать эти жетоны.

В этом примере создается конфликт сдвига/уменьшения. Документация говорит, что:

Shift/уменьшить конфликты разрешаются в пользу перехода, если нет нет оператора деклараций старшинства.

Это означает, что, когда ваш анализатор находится в месте, обозначенном |

of 3 
    4| 
5 

и видит новую линию, может быть два варианта:

  • это может быть следующий case_condition так синтаксический анализатор должен продолжать «сдвиг» читать дальше
  • это может быть конец заявления, поэтому парсеру нужно все обрабатывать до утверждения и pu t it on stack или short «reduce»

Поскольку эти конфликты всегда разрешены для смены, вы не можете поместить следующий оператор после запуска! Вам нужно изменить свою грамматику. Работа с ним до yecc:file/1 не вызывает никаких предупреждений.

ПОДСКАЗКА: Отступ внутри все дело так:

case 1 
    of 2 
     3 
    of 3 
     4 
5 

Таким образом, вы ясно говорят, что case одно заявление и 5 это совсем другое. Мои знания о парсерах стали немного ржавыми, но я считаю, что вы не сможете писать грамматику, которая может различать между case_condition и statement с парсером слева направо, если вы не добавляете отступы или какой-то терминатор ,