Jison не предполагает правильную грамматику

#javascript #parsing #parser-generator #jison

#javascript #синтаксический анализ #анализатор-генератор #jison

Вопрос:

Я создаю грамматику в jison

Это мой файл jison:

sgr.jison

 /*
AUX VARIABLES
*/
%{
var contratos = "(E1:ENTIDADE)-[C:CONTRATO] -> (E2:ENTIDADE)";
var dataArray = {};

function
translateQuery(dataArray) 
{
    var finalQuery = dataArray["Listar"]   " "
                       dataArray["Contratos"]   "n"
                       dataArray["Onde"]   " "
                       dataArray["condition"]   "n"
                       dataArray["Retornar"]   " "
                       dataArray["returnAttributes"]
    console.log("n"   finalQuery)
}

%}


/* description: Parses end executes mathematical expressions. */

/* lexical grammar */
%lex

%%
s                      /* skip whitespace */
Listar                  return 'MATCH'
Contratos               return 'CONTRACTS'
Onde                    return 'WHERE'
Retornar                return 'RETURN'
e                       return 'AND'
ou                      return 'OR'

","                     return 'DELIMITER'
";"                     return 'END'

[><>=<==]               return 'MATH_SYMBOL'
[0-9] b                return 'VALUE'
[A-Za-z0-9.] b         return 'ENTITY_ATTRIBUTE'
["]                     return 'QUOTATION_MARK'






/lex

%start expressions

%% /* language grammar */

expressions :
    regra               
        {
            /*
            ADD SOMETHING 
            ONLY IF NEEDED
            */
        }
    | /* | significa um OU o que quer dizer que isto aqui pode ter mais do que uma regra ISTO E FEITO PELA RECURSIVIDADE*/
    expressions regra
        {
            /*
            ADD SOMETHING 
            ONLY IF NEEDED
            */
        }
;

 regra: 
    MATCH CONTRACTS
    WHERE condition
    RETURN returnAttributes END
        {
            $$ = $1   " "
                  $2   " "
                  $3   " "
                  $4   " "
                  $5   " "
                  $6   " "
                dataArray[$1] = "MATCH"
                dataArray[$2] = contratos
                dataArray[$3] = "WHERE"
                dataArray["condition"] = $4
                dataArray[$5] = "RETURN"
                dataArray["returnAttributes"] = $6
                /*ESTA FUNCAO TRATA DE TRADUZIR A QUERY QUE E INTERPRETADA*/
                translateQuery(dataArray)
        }
 ;

 condition:
    ENTITY_ATTRIBUTE MATH_SYMBOL
        {
            $$ = $1    " "
                  $2
        }
    |
    condition VALUE
        {
            $$ = $1    " "
                  $2
        }
    |
    condition QUOTATION_MARK ENTITY_ATTRIBUTE QUOTATION_MARK
        {
                $$ = $1    " "
                  $2   " "
                  $3   " "
                  $4
        }
    |
    condition AND ENTITY_ATTRIBUTE MATH_SYMBOL VALUE
        {
            $$ = $1    " "
                  $2   " "
                  $3   " "
                  $4   " "
                  $5
        }
    |
    condition OR ENTITY_ATTRIBUTE MATH_SYMBOL VALUE
        {
            $$ = $1    " "
                  $2   " "
                  $3   " "
                  $4   " "
                  $5
        }
    |
    condition AND ENTITY_ATTRIBUTE MATH_SYMBOL QUOTATION_MARK ENTITY_ATTRIBUTE QUOTATION_MARK
        {
            $$ = $1    " "
                  $2   " "
                  $3   " "
                  $4   " "
                  $5   " "
                  $6   " "
                  $7
        }
    |
    condition OR ENTITY_ATTRIBUTE MATH_SYMBOL QUOTATION_MARK ENTITY_ATTRIBUTE QUOTATION_MARK
        {
            $$ = $1    " "
                  $2   " "
                  $3   " "
                  $4   " "
                  $5   " "
                  $6   " "
                  $7
        }
 ;

 returnAttributes:
    ENTITY_ATTRIBUTE
        {
            $$ = $1
        }
    |
    returnAttributes DELIMITER ENTITY_ATTRIBUTE
        {
            $$ = $1   ""
                  $2   " "
                  $3
        }
 ;
  

В моем определении лексической грамматики у меня есть:

 e     return 'AND'
ou    return 'OR'
  

итак, всякий раз, когда в моем тестовом файле были обнаружены «e» или «ou», они должны возвращать «И» и «ИЛИ» соответственно.

Проблема в том, что когда я его тестирую, вместо того, чтобы возвращать мне «И» и «ИЛИ», он возвращает мне «e» и «ou».

Взгляните:

Это мой тестовый файл:

test.sgr

 Listar Contratos
Onde C.preco=1000
Retornar C.Preco, C.NifAdjudicante,C.NifAdjudicataria;


Listar Contratos
Onde C.preco=1000 e E1.name="ESTG"
Retornar C.Preco, C.NifAdjudicante,C.NifAdjudicataria;


Listar Contratos
Onde C.preco=1000 e E1.name="ESTG" e C.TipoProcedimento="ADS"
Retornar C.Preco, C.NifAdjudicante,C.NifAdjudicataria;


Listar Contratos
Onde E1.name="ESTG"
Retornar E1.name,C.Preco,C.NifAdjudicante,C.NifAdjudicataria;


Listar Contratos
Onde E1.name="ESTG" e C.preco=1000 ou C.preco>1000 
Retornar E1.name,C.Preco,C.NifAdjudicante,C.NifAdjudicataria;
  

Выходные данные должны быть:

 MATCH (E1:ENTIDADE)-[C:CONTRATO] -> (E2:ENTIDADE)
WHERE C.preco = 1000
RETURN C.Preco, C.NifAdjudicante, C.NifAdjudicataria

MATCH (E1:ENTIDADE)-[C:CONTRATO] -> (E2:ENTIDADE)
WHERE C.preco = 1000 AND E1.name = " ESTG "
RETURN C.Preco, C.NifAdjudicante, C.NifAdjudicataria

MATCH (E1:ENTIDADE)-[C:CONTRATO] -> (E2:ENTIDADE)
WHERE C.preco = 1000 AND E1.name = " ESTG " AND C.TipoProcedimento = " ADS "
RETURN C.Preco, C.NifAdjudicante, C.NifAdjudicataria

MATCH (E1:ENTIDADE)-[C:CONTRATO] -> (E2:ENTIDADE)
WHERE E1.name = " ESTG "
RETURN E1.name, C.Preco, C.NifAdjudicante, C.NifAdjudicataria

MATCH (E1:ENTIDADE)-[C:CONTRATO] -> (E2:ENTIDADE)
WHERE E1.name = " ESTG " AND C.preco = 1000 OR C.preco > 1000
RETURN E1.name, C.Preco, C.NifAdjudicante, C.NifAdjudicataria
  

Однако выходные данные:

выводит

Что я сделал не так?

Ответ №1:

Токены, идентифицированные в вашем лексическом анализаторе, имеют тип токена, который представляет собой строку, возвращаемую из действия сканирования, и соответствующий текст, который лексический сканер сохраняет в своем yytext свойстве, из которого анализатор инициализирует семантическое значение токена. (Это не очень хорошо описано в документации.)

Итак, в этом действии:

 condition:
    condition OR ENTITY_ATTRIBUTE MATH_SYMBOL VALUE
        {
            $$ = $1    " "
                 $2   " "
                 $3   " "
                 $4   " "
                 $5
        }
  

значение $2 — это текст, соответствующий токену, тип токена которого был "OR" , то есть ou . Если вам нужна строка "OR" , это то, что вы должны были поместить в действие:

 condition:
    condition OR ENTITY_ATTRIBUTE MATH_SYMBOL VALUE
        {
            $$ = $1   " OR "
                 $3   " "
                 $4   " "
                 $5
        }
  

(Сказав это, я должен сказать, что я думаю, что есть лучшие способы структурирования AST. Но если это работает для вас, это круто.)