Базовый PHP-подобный интерпретатор, использующий flex и bizon. Уменьшить / уменьшить и переместить / уменьшить конфликты - PullRequest
0 голосов
/ 03 июля 2018

Я пишу интерпретатор, похожий на PHP, и у меня есть некоторые проблемы с конфликтами сдвига / уменьшения и уменьшения / уменьшения. Пусть кто-нибудь поможет мне понять сдвиг / уменьшение и уменьшение / уменьшение конфликтов.

Я должен написать и интерпретировать эти символы и выражения выражения, начиная с "волшебного" @ символа, например. @ if (cond) ... @end; . Так что "if" должно быть отражено, а @ if (cond) должно быть интерпретировано

Проблема: scriptlang.y содержит 21 конфликт сдвига / уменьшения и 2 конфликта уменьшения / уменьшения.

%union {
    char* sval;
}
%token <sval> IDENTIFIER
%token <sval> RBRACKET
%token <sval> LBRACKET
%token <sval> KWSWITCH
%token <sval> KWIF
%token <sval> MAGICESC
%token MAGIC
%token ENDSTM

%type <sval> filechar

%start script

%%
script:
   commands
;
commands:   
    /* empty */
    | command 
    | commands command
;
command:
    filechar {
        analyser_echo($1,"filechar",analyser_canEcho);
    }
    | magic_command {}
;
filechar:
    IDENTIFIER
    | LBRACKET
    | RBRACKET
    | KWSWITCH
    | KWIF
    | MAGICESC
;
magic_command:
    MAGIC valuation
    | MAGIC alternative
;
valuation:
    LBRACKET IDENTIFIER RBRACKET {
        fprintf(yyout, "<val>");
    }
;
alternative:
    switch_alternative
    | if_alternative
;
switch_alternative:
    switch_block end_stm
;
switch_block:
    switch_stm
    | switch_stm commands
;
switch_stm:
    KWSWITCH LBRACKET IDENTIFIER RBRACKET {}
;
if_alternative:
    if_block end_stm
;
if_block:
    if_stm
    | if_stm commands
;
if_stm:
    KWIF LBRACKET IDENTIFIER RBRACKET {}
;
end_stm:
    ENDSTM
;
%%

содержимое файла flex:

"@@" {
    yylval.sval = "@"; 
    return MAGICESC;
}
"@" {
    return MAGIC;
}
"(" {
    yylval.sval = yytext; 
    return LBRACKET;
}
")" {
    yylval.sval = yytext; 
    return RBRACKET;
}
"@end;" { 
    return ENDSTM;
}
"if" {
    yylval.sval = yytext; 
    return KWIF;
}
"switch" {
    yylval.sval = yytext; 
    return KWSWITCH;
}
[a-zA-Z][_a-zA-Z0-9]* {
    yylval.sval = yytext; 
    return IDENTIFIER;
}
\n|. {
    if(analyser_canEcho>0){
        ECHO;
    }
}
%%

1 Ответ

0 голосов
/ 03 июля 2018

Основной проблемой, приводящей к конфликтам, является ваша обработка commands. Ваше намерение состоит в том, чтобы определить commands как ноль или более command с, что записывается следующим образом:

commands: %empty
        | commands command

Если бы вы хотели настаивать на наличии хотя бы одной команды, вы бы написали:

commands: command
        | commands command

Смешивание двух форм не будет работать, так как синтаксический анализатор не будет знать, начинать ли последовательность command s с нуля (%empty) или с одного command. Вы должны попытаться точно понять, почему это приводит к двусмысленности; Вы найдете несколько примеров подобных проблем на этом сайте. Например, см. этот вопрос .

Это вызывает 21 сдвиг / уменьшение конфликтов. Конфликты уменьшения / уменьшения являются результатом любопытных постановок:

switch_block: switch_stm commands
if_block: if_stm commands
Операторы

if и switch представляют собой отдельные элементы command внутри последовательности commands; все, что следует за оператором switch или if, будет следующим command в commands. Определение switch_block для включения следующих команд совершенно неоднозначно: фактически, это говорит о том, что следующий command все еще может быть частью switch_block, или это может быть command после switch_block.


Выше я специально рассмотрел вопрос, который вы задали: конфликт таблиц анализа в вашей грамматике. Существуют и другие проблемы с вашей грамматикой и лексическими спецификациями, и я настоятельно рекомендую вам изучить любые материалы, которые вам дали о зубре / гибкости, и / или прочитать инструкции bison и flex . .

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

  1. Обработка семантических значений. Никогда не требуется, чтобы синтаксическое ключевое слово имело свое собственное представление в качестве семантического значения; действительно, синтаксические ключевые слова редко требуют семантических значений вообще. Если токен требует, чтобы его семантическое значение было его представлением, вы должны помнить, что yytext является указателем на личный буфер данных, который вам не принадлежит и который будет изменен без предупреждения. Поэтому требуется копирование.

  2. Встраиваемые языки, такие как ваш вариант PHP, включают два разных лексических контекста. У вас есть внешний, по сути не интерпретируемый контекст, и встроенный контекст, который содержится между @ и @end;. (F) lex предоставляет начальные условия , чтобы помочь справиться с такого рода встраиванием. В руководстве есть несколько примеров, и на этом сайте еще много информации.

...