внимание, правило не может быть сопоставлено для лексера с использованием flex

#bison #flex-lexer #yacc #lexer

Вопрос:

Я использую flex и bison для создания лексического анализатора и синтаксического анализатора для языка программирования, но когда я компилирую свою программу, я получаю предупреждение

правило не может быть сопоставлено

для моего lex.l, в частности, для моих токенов «var», «функция», «если», «еще» и «в то время как» в моем лексере (файл lex.l).

Я прикрепляю файлы lex.l и parse.y, которые представляют мой лексер и синтаксический анализатор соответственно. Любая информация была бы очень признательна

лекс.л

 %{
#include "util.h"
#include "node.h"
#include "parse.tab.h"

void yyerror(const char *fmt, ...);
int create_token(int tag, const char *lexeme);

// global variable pointing to string containing name of input file
//var a b
//a   b
char *g_srcfile;
%}

%option yylineno
%option noyywrap

%%

[A-Za-z][A-Za-z0-9]*         { return create_token(TOK_IDENTIFIER, yytext); }
       
"-"?(0|[1-9][0-9]*)("."[0-9]*)?((e|E)(" "|"-")?[0-9] )? {
                      return create_token(TOK_NUMBER, yytext); }

"("                 { return create_token(TOK_LPARENTHESIS, yytext); }
")"                 { return create_token(TOK_RPARENTHESIS, yytext); }
"{"                 { return create_token(TOK_LCURLY_BRACE, yytext); }
"}"                 { return create_token(TOK_RCURLY_BRACE, yytext); }

";"                 { return create_token(TOK_COLON, yytext); }
","                 { return create_token(TOK_COMMA, yytext); }

" "                 { return create_token(TOK_ADD, yytext); }
"-"                 { return create_token(TOK_SUBTRACT, yytext); }
"*"                 { return create_token(TOK_MULTIPLY, yytext); }
"/"                 { return create_token(TOK_DIVIDE, yytext); }


"=="                 { return create_token(TOK_CHECK_EQUAL, yytext); }
"!="                 { return create_token(TOK_NOT_EQUAL, yytext); }
"<"                 { return create_token(TOK_LESS, yytext); }
">"                 { return create_token(TOK_GREATER, yytext); }
"<="                 { return create_token(TOK_LESS_EQUAL, yytext); }
">="                 { return create_token(TOK_GREATER_EQUAL, yytext); }

"amp;amp;"                 { return create_token(TOK_AND, yytext); }
"||"                 { return create_token(TOK_OR, yytext); }
"="                 { return create_token(TOK_EQUAL, yytext); }

"var"                 { return create_token(TOK_VAR, yytext); }
"function"                 { return create_token(TOK_FUNCTION, yytext); }
"if"                 { return create_token(TOK_IF, yytext); }
"else"                 { return create_token(TOK_ELSE, yytext); }
"while"                 { return create_token(TOK_WHILE, yytext); }

"//"                 { return create_token(TOK_COMMENT, yytext); }

[ trnv]         { /* ignore whitespace */ }

.                            { yyerror("Unknown character: %cn", yytext[0]); }


%%

void lexer_set_source_file(const char *filename) {
  g_srcfile = xstrdup(filename);
}

int create_token(int tag, const char *lexeme) {
  yylval.node = node_alloc_str_copy(tag, yytext);

  return tag;
}

 

Вот мой синтаксический анализатор

разбор.y

 %{
#include <stdio.h>
#include <stdarg.h>
#include "util.h"
#include "node.h"
#include "grammar_symbols.h"

int yylex(void);
void yyerror(const char *fmt, ...);

// global variable to point to the root of the parse tree
struct Node *g_translation_unit;
struct Node *g_expression;
struct Node *g_definition;
struct Node *g_parse_tree;
%}

%union {
    struct Node *node;
}

/* TODO: define terminal and nonterminal symbols */

%token<node> TOK_IDENTIFIER

%type<node> translation_unit
%type<node> definition

%type<node> expression variable_declaration_statement if_statement
%type<node> if_else_statement while_statement unary_expression primary_expression
%type<node> parenthesized_subexpression function_call opt_argument_list
%type<node> statement opt_parameter_list statement_list function
%type<node> expression_statement 

%token<node> TOK_LPARENTHESIS TOK_RPARENTHESIS TOK_LCURLY_BRACE TOK_RCURLY_BRACE 
%token<node> TOK_COLON TOK_COMMA
%token<node> TOK_NUMBER TOK_STRING_LITERAL
%token<node> TOK_ADD TOK_SUBTRACT TOK_MULTIPLY TOK_DIVIDE 
%token<node> TOK_CHECK_EQUAL TOK_NOT_EQUAL TOK_LESS TOK_GREATER TOK_LESS_EQUAL TOK_GREATER_EQUAL TOK_AND TOK_OR TOK_EQUAL
%token<node> TOK_VAR TOK_FUNCTION TOK_IF TOK_ELSE TOK_WHILE 
%token<node> TOK_COMMENT


%%

/* TODO: add actual grammar rules */
translation_unit
    : definition { g_translation_unit = $ = node_build1(NODE_translation_unit, $1); }
    ;

definition
    : statement { g_definition = $ = node_build1(NODE_definition, $1); }
  | function { $ = g_definition = node_build1(NODE_definition, $1); }
    ;


... deleted not related code



%%

void yyerror(const char *fmt, ...) {
  extern char *g_srcfile;
  extern int yylineno, g_col;

  va_list args;

  va_start(args, fmt);
  int error_col = 1; // TODO: determine column number
  fprintf(stderr, "%s:%d:%d: Error: ", g_srcfile, yylineno, error_col);
  verr_fatal(fmt, args);
  va_end(args);
}

 

Комментарии:

1. Вы можете значительно упростить себе жизнь, буквально трактуя все отдельные специальные символы и убирая все их правила. Просто используйте . return yytext[0]; в нижней части лексера и используйте '=', '<', '>' и т. Д. буквально в правилах грамматики.

Ответ №1:

Ключевые слова не могут быть сопоставлены, потому что ваше правило идентификации стоит на первом месте в вашем файле. Каждое ключевое слово также является допустимым идентификатором; вам нужно, чтобы правило ключевых слов имело приоритет, что оно будет делать, если оно появится раньше.

Комментарии:

1. Пожалуйста, сделайте себе одолжение и прочитайте руководство по эксплуатации Flex. Это кратко и по существу. Правило упорядочения находится в разделе о том, как сопоставляются шаблоны , а сам синтаксис шаблона описан в разделе Шаблоны .