Я пишу Lex/Yacc код для обнаружения #include < некоторые библиотеки> или #include «некоторый заголовок файла» Это мои коды:правила Написание Lex и Yacc обнаружить #include в языке C
Lex код
%e 1019
%p 2807
%n 371
%k 284
%a 1213
%o 1117
O [0-7]
D [0-9]
NZ [1-9]
L [a-zA-Z_] /***********************/
A [a-zA-Z_0-9]
H [a-fA-F0-9]
HP (0[xX])
E ([Ee][+-]?{D}+)
P ([Pp][+-]?{D}+)
FS (f|F|l|L)
IS (((u|U)(l|L|ll|LL)?)|((l|L|ll|LL)(u|U)?))
CP (u|U|L)
SP (u8|u|U|L)
ES (\\(['"\?\\abfnrtv]|[0-7]{1,3}|x[a-fA-F0-9]+))
WS [ \t\v\n\f]
%{
#include <stdio.h>
#include "y.tab.h"
extern void yyerror(const char *);
extern int sym_type(const char *);
#define sym_type(identifier) IDENTIFIER
static void comment(void);
static int check_type(void);
%}
%%
{L} {yylval.a=strdup(yytext); return STATEMENT;} /*****************/
"/*" { comment(); }
"//".* { /* consume //-comment */ }
"include" { yylval.a=strdup(yytext); return(INCLUDE); }
"void" { yylval.a=strdup(yytext); return(VOID); }
"int" { yylval.a=strdup(yytext); return(INT); }
"long" { yylval.a=strdup(yytext); return(LONG); }
"char" { yylval.a=strdup(yytext); return(CHAR); }
"short" { yylval.a=strdup(yytext); return(SHORT); }
"signed" { yylval.a=strdup(yytext); return(SIGNED); }
"double" { yylval.a=strdup(yytext); return(DOUBLE); }
"unsigned" { yylval.a=strdup(yytext); return(UNSIGNED); }
"float" { yylval.a=strdup(yytext); return(FLOAT); }
"auto" { yylval.a=strdup(yytext); return(AUTO); }
"extern" { yylval.a=strdup(yytext); return(EXTERN); }
"register" { yylval.a=strdup(yytext); return(REGISTER); }
"static" { yylval.a=strdup(yytext); return(STATIC); }
"const" { yylval.a=strdup(yytext); return(CONST); }
"restrict" { yylval.a=strdup(yytext); return(RESTRICT); }
"volatile" { yylval.a=strdup(yytext); return(VOLATILE); }
"_Atomic" { yylval.a=strdup(yytext); return ATOMIC; }
"break" { yylval.a=strdup(yytext); return(BREAK); }
"case" { yylval.a=strdup(yytext); return(CASE); }
"continue" { yylval.a=strdup(yytext); return(CONTINUE); }
"default" { yylval.a=strdup(yytext); return(DEFAULT); }
"do" { yylval.a=strdup(yytext); return(DO); }
"else" { yylval.a=strdup(yytext); return(ELSE); }
"enum" { yylval.a=strdup(yytext); return(ENUM); }
"for" { yylval.a=strdup(yytext); return(FOR); }
"goto" { yylval.a=strdup(yytext); return(GOTO); }
"if" { yylval.a=strdup(yytext); return(IF); }
"inline" { yylval.a=strdup(yytext); return(INLINE); }
"return" { yylval.a=strdup(yytext); return(RETURN); }
"sizeof" { yylval.a=strdup(yytext); return(SIZEOF); }
"struct" { yylval.a=strdup(yytext); return(STRUCT); }
"switch" { yylval.a=strdup(yytext); return(SWITCH); }
"typedef" { yylval.a=strdup(yytext); return(TYPEDEF); }
"union" { yylval.a=strdup(yytext); return(UNION); }
"while" { yylval.a=strdup(yytext); return(WHILE); }
"_Alignas" { yylval.a=strdup(yytext); return ALIGNAS; }
"_Alignof" { yylval.a=strdup(yytext); return ALIGNOF; }
"_Bool" { yylval.a=strdup(yytext); return BOOL; }
"_Complex" { yylval.a=strdup(yytext); return COMPLEX; }
"_Generic" { yylval.a=strdup(yytext); return GENERIC; }
"_Imaginary" { yylval.a=strdup(yytext); return IMAGINARY; }
"_Noreturn" { yylval.a=strdup(yytext); return NORETURN; }
"_Static_assert" { yylval.a=strdup(yytext); return STATIC_ASSERT; }
"_Thread_local" { yylval.a=strdup(yytext); return THREAD_LOCAL; }
"__func__" { yylval.a=strdup(yytext); return FUNC_NAME; }
{L}{A}* { return check_type(); }
{HP}{H}+{IS}? { yylval.a=strdup(yytext); return I_CONSTANT; }
{NZ}{D}*{IS}? { yylval.a=strdup(yytext); return I_CONSTANT; }
"0"{O}*{IS}? { yylval.a=strdup(yytext); return I_CONSTANT; }
{CP}?"'"([^'\\\n]|{ES})+"'" { return I_CONSTANT; } /**/
{D}+{E}{FS}? { yylval.a=strdup(yytext); return F_CONSTANT; }
{D}*"."{D}+{E}?{FS}? { yylval.a=strdup(yytext); return F_CONSTANT; }
{D}+"."{E}?{FS}? { yylval.a=strdup(yytext); return F_CONSTANT; }
{HP}{H}+{P}{FS}? { yylval.a=strdup(yytext);return F_CONSTANT; }
{HP}{H}*"."{H}+{P}{FS}? { yylval.a=strdup(yytext); return F_CONSTANT; }
{HP}{H}+"."{P}{FS}? { yylval.a=strdup(yytext); return F_CONSTANT; }
({SP}?\"([^"\\\n]|{ES})*\"{WS}*)+ { return STRING_LITERAL; }
"..." { yylval.a=strdup(yytext); return ELLIPSIS; }
">>=" { yylval.a=strdup(yytext); return RIGHT_ASSIGN; }
"<<=" { yylval.a=strdup(yytext); return LEFT_ASSIGN; }
"+=" { yylval.a=strdup(yytext); return ADD_ASSIGN; }
"-=" { yylval.a=strdup(yytext); return SUB_ASSIGN; }
"*=" { yylval.a=strdup(yytext); return MUL_ASSIGN; }
"/=" { yylval.a=strdup(yytext); return DIV_ASSIGN; }
"%=" { yylval.a=strdup(yytext); return MOD_ASSIGN; }
"&=" { yylval.a=strdup(yytext); return AND_ASSIGN; }
"^=" { yylval.a=strdup(yytext); return XOR_ASSIGN; }
"|=" { yylval.a=strdup(yytext); return OR_ASSIGN; }
">>" { yylval.a=strdup(yytext); return RIGHT_OP; }
"<<" { yylval.a=strdup(yytext); return LEFT_OP; }
"++" { yylval.a=strdup(yytext); return INC_OP; }
"--" { yylval.a=strdup(yytext); return DEC_OP; }
"->" { yylval.a=strdup(yytext); return PTR_OP; }
"&&" { yylval.a=strdup(yytext); return AND_OP; }
"||" { yylval.a=strdup(yytext); return OR_OP; }
"<=" { yylval.a=strdup(yytext); return LE_OP; }
">=" { yylval.a=strdup(yytext); return GE_OP; }
"==" { yylval.a=strdup(yytext); return EQ_OP; }
"!=" { yylval.a=strdup(yytext); return NE_OP; }
";" { yylval.a=strdup(yytext); return ';'; }
("{"|"<%") { yylval.a=strdup(yytext); return '{'; }
("}"|"%>") { yylval.a=strdup(yytext); return '}'; }
"," { yylval.a=strdup(yytext); return ','; }
":" { yylval.a=strdup(yytext); return ':'; }
"=" { yylval.a=strdup(yytext); return '='; }
"(" { yylval.a=strdup(yytext); return '('; }
")" { yylval.a=strdup(yytext); return ')'; }
("["|"<:") { yylval.a=strdup(yytext); return '['; }
("]"|":>") { yylval.a=strdup(yytext); return ']'; }
"." { yylval.a=strdup(yytext); return '.'; }
"&" { yylval.a=strdup(yytext); return '&'; }
"!" { yylval.a=strdup(yytext); return '!'; }
"~" { yylval.a=strdup(yytext); return '~'; }
"-" { yylval.a=strdup(yytext); return '-'; }
"+" { yylval.a=strdup(yytext); return '+'; }
"*" { yylval.a=strdup(yytext); return '*'; }
"/" { yylval.a=strdup(yytext); return '/'; }
"%" { yylval.a=strdup(yytext); return '%'; }
"<" { yylval.a=strdup(yytext); return '<'; } /***********************/
">" { yylval.a=strdup(yytext); return '>'; } /***********************/
"^" { yylval.a=strdup(yytext); return '^'; }
"|" { yylval.a=strdup(yytext); return '|'; }
"?" { yylval.a=strdup(yytext); return '?'; }
"#" {yylval.a=strdup(yytext); return '#'; } /***********************/
{WS}+ { /* whitespace separates tokens */ }
. { /* discard bad characters */ }
%%
int yywrap(void)
{
return 1;
}
static void comment(void)
{
int c;
while ((c = input()) != 0)
if (c == '*')
{
printf("1: %d\n",c);
while ((c = input()) == '*')
;
printf("2: %d\n",c);
if (c == '/')
return;
if (c == 0)
printf("3: %d\n",c);
break;
}
yyerror("unterminated comment");
}
static int check_type(void)
{
switch (sym_type(yytext))
{
case TYPEDEF_NAME:
{
return TYPEDEF_NAME;
}
case ENUMERATION_CONSTANT:
return ENUMERATION_CONSTANT;
default:
{
yylval.a=strdup(yytext);
return IDENTIFIER;
}
}
}
Yacc код
%token IDENTIFIER I_CONSTANT F_CONSTANT STRING_LITERAL FUNC_NAME SIZEOF
%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN
%token TYPEDEF_NAME ENUMERATION_CONSTANT
%token TYPEDEF EXTERN STATIC AUTO REGISTER INLINE
%token CONST RESTRICT VOLATILE
%token BOOL CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE VOID
%token COMPLEX IMAGINARY
%token STRUCT UNION ENUM ELLIPSIS
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
%token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATIC_ASSERT THREAD_LOCAL
%token INCLUDE STATEMENT /********************/
%start translation_unit
%{
#include<stdio.h>
#include<string.h>
extern FILE* yyin;
int yylex();
void yyerror(const char *s);
%}
%union{
char* a;
char* b;
}
%type <a>IDENTIFIER
%type <a>SIGNED UNSIGNED
%type <a>INT CHAR DOUBLE FLOAT LONG SHORT
%type <b>EXTERN STATIC AUTO REGISTER
%%
include /*********************/
: '#' INCLUDE '<' STATEMENT '>' /*********************/
| '#' INCLUDE '"' STATEMENT '"' /*********************/
;
primary_expression
: IDENTIFIER
| constant
| string
| '(' expression ')'
| generic_selection
;
constant
: I_CONSTANT /* includes character_constant */
| F_CONSTANT
| ENUMERATION_CONSTANT /* after it has been defined as such */
;
enumeration_constant /* before it has been defined as such */
: IDENTIFIER
;
string
: STRING_LITERAL
| FUNC_NAME
;
generic_selection
: GENERIC '(' assignment_expression ',' generic_assoc_list ')'
;
generic_assoc_list
: generic_association
| generic_assoc_list ',' generic_association
;
generic_association
: type_name ':' assignment_expression
| DEFAULT ':' assignment_expression
;
postfix_expression
: primary_expression
| postfix_expression '[' expression ']'
| postfix_expression '(' ')'
| postfix_expression '(' argument_expression_list ')'
| postfix_expression '.' IDENTIFIER
| postfix_expression PTR_OP IDENTIFIER
| postfix_expression INC_OP
| postfix_expression DEC_OP
| '(' type_name ')' '{' initializer_list '}'
| '(' type_name ')' '{' initializer_list ',' '}'
;
argument_expression_list
: assignment_expression
| argument_expression_list ',' assignment_expression
;
unary_expression
: postfix_expression
| INC_OP unary_expression
| DEC_OP unary_expression
| unary_operator cast_expression
| SIZEOF unary_expression
| SIZEOF '(' type_name ')'
| ALIGNOF '(' type_name ')'
;
unary_operator
: '&'
| '*'
| '+'
| '-'
| '~'
| '!'
;
cast_expression
: unary_expression
| '(' type_name ')' cast_expression
;
multiplicative_expression
: cast_expression
| multiplicative_expression '*' cast_expression
| multiplicative_expression '/' cast_expression
| multiplicative_expression '%' cast_expression
;
additive_expression
: multiplicative_expression
| additive_expression '+' multiplicative_expression
| additive_expression '-' multiplicative_expression
;
shift_expression
: additive_expression
| shift_expression LEFT_OP additive_expression
| shift_expression RIGHT_OP additive_expression
;
relational_expression
: shift_expression
| relational_expression '<' shift_expression
| relational_expression '>' shift_expression
| relational_expression LE_OP shift_expression
| relational_expression GE_OP shift_expression
;
equality_expression
: relational_expression
| equality_expression EQ_OP relational_expression
| equality_expression NE_OP relational_expression
;
and_expression
: equality_expression
| and_expression '&' equality_expression
;
exclusive_or_expression
: and_expression
| exclusive_or_expression '^' and_expression
;
inclusive_or_expression
: exclusive_or_expression
| inclusive_or_expression '|' exclusive_or_expression
;
logical_and_expression
: inclusive_or_expression
| logical_and_expression AND_OP inclusive_or_expression
;
logical_or_expression
: logical_and_expression
| logical_or_expression OR_OP logical_and_expression
;
conditional_expression
: logical_or_expression
| logical_or_expression '?' expression ':' conditional_expression
;
assignment_expression
: conditional_expression
| unary_expression assignment_operator assignment_expression
;
assignment_operator
: '='
| MUL_ASSIGN
| DIV_ASSIGN
| MOD_ASSIGN
| ADD_ASSIGN
| SUB_ASSIGN
| LEFT_ASSIGN
| RIGHT_ASSIGN
| AND_ASSIGN
| XOR_ASSIGN
| OR_ASSIGN
;
expression
: assignment_expression
| expression ',' assignment_expression
;
constant_expression
: conditional_expression /* with constraints */
;
declaration
: declaration_specifiers ';' /* no rule need*/
| declaration_specifiers init_declarator_list ';' { printf("declaration_specifier:%s\nThe init_declarator_list:%s \nsemicolon:%s\n",$<a>1,$<a>2,$<a>3);
}
| static_assert_declaration
;
declaration_specifiers
: storage_class_specifier declaration {printf("Storage_class_specifier:%s \ndeclaration_specifiers:%s \n",$<b>1,$<b>2);}
| storage_class_specifier
| type_specifier declaration_specifiers
| type_specifier
| type_qualifier declaration_specifiers
| type_qualifier
| function_specifier declaration_specifiers
| function_specifier
| alignment_specifier declaration_specifiers
| alignment_specifier
;
init_declarator_list
: init_declarator
| init_declarator_list ',' init_declarator
;
init_declarator
: declarator '=' initializer
| declarator
;
storage_class_specifier
: TYPEDEF /* identifiers must be flagged as TYPEDEF_NAME */
| EXTERN
| STATIC
| THREAD_LOCAL
| AUTO
| REGISTER
;
type_specifier
: VOID
| CHAR
| SHORT
| INT
| LONG
| FLOAT
| DOUBLE
| SIGNED
| UNSIGNED
| BOOL
| COMPLEX
| IMAGINARY /* non-mandated extension */
| atomic_type_specifier
| struct_or_union_specifier
| enum_specifier
| TYPEDEF_NAME /* after it has been defined as such */
;
struct_or_union_specifier
: struct_or_union '{' struct_declaration_list '}'
| struct_or_union IDENTIFIER '{' struct_declaration_list '}'
| struct_or_union IDENTIFIER
;
struct_or_union
: STRUCT
| UNION
;
struct_declaration_list
: struct_declaration
| struct_declaration_list struct_declaration
;
struct_declaration
: specifier_qualifier_list ';' /* for anonymous struct/union */
| specifier_qualifier_list struct_declarator_list ';'
| static_assert_declaration
;
specifier_qualifier_list
: type_specifier specifier_qualifier_list
| type_specifier
| type_qualifier specifier_qualifier_list
| type_qualifier
;
struct_declarator_list
: struct_declarator
| struct_declarator_list ',' struct_declarator
;
struct_declarator
: ':' constant_expression
| declarator ':' constant_expression
| declarator
;
enum_specifier
: ENUM '{' enumerator_list '}'
| ENUM '{' enumerator_list ',' '}'
| ENUM IDENTIFIER '{' enumerator_list '}'
| ENUM IDENTIFIER '{' enumerator_list ',' '}'
| ENUM IDENTIFIER
;
enumerator_list
: enumerator
| enumerator_list ',' enumerator
;
enumerator /* identifiers must be flagged as ENUMERATION_CONSTANT */
: enumeration_constant '=' constant_expression
| enumeration_constant
;
atomic_type_specifier
: ATOMIC '(' type_name ')'
;
type_qualifier
: CONST
| RESTRICT
| VOLATILE
| ATOMIC
;
function_specifier
: INLINE
| NORETURN
;
alignment_specifier
: ALIGNAS '(' type_name ')'
| ALIGNAS '(' constant_expression ')'
;
declarator
: pointer direct_declarator
| direct_declarator
;
direct_declarator
: IDENTIFIER
| '(' declarator ')'
| direct_declarator '[' ']'
| direct_declarator '[' '*' ']'
| direct_declarator '[' STATIC type_qualifier_list assignment_expression ']'
| direct_declarator '[' STATIC assignment_expression ']'
| direct_declarator '[' type_qualifier_list '*' ']'
| direct_declarator '[' type_qualifier_list STATIC assignment_expression ']'
| direct_declarator '[' type_qualifier_list assignment_expression ']'
| direct_declarator '[' type_qualifier_list ']'
| direct_declarator '[' assignment_expression ']'
| direct_declarator '(' parameter_type_list ')'
| direct_declarator '(' ')'
| direct_declarator '(' identifier_list ')'
;
pointer
: '*' type_qualifier_list pointer
| '*' type_qualifier_list
| '*' pointer
| '*'
;
type_qualifier_list
: type_qualifier
| type_qualifier_list type_qualifier
;
parameter_type_list
: parameter_list ',' ELLIPSIS
| parameter_list
;
parameter_list
: parameter_declaration
| parameter_list ',' parameter_declaration
;
parameter_declaration
: declaration_specifiers declarator
| declaration_specifiers abstract_declarator
| declaration_specifiers
;
identifier_list
: IDENTIFIER
| identifier_list ',' IDENTIFIER
;
type_name
: specifier_qualifier_list abstract_declarator
| specifier_qualifier_list
;
abstract_declarator
: pointer direct_abstract_declarator
| pointer
| direct_abstract_declarator
;
direct_abstract_declarator
: '(' abstract_declarator ')'
| '[' ']'
| '[' '*' ']'
| '[' STATIC type_qualifier_list assignment_expression ']'
| '[' STATIC assignment_expression ']'
| '[' type_qualifier_list STATIC assignment_expression ']'
| '[' type_qualifier_list assignment_expression ']'
| '[' type_qualifier_list ']'
| '[' assignment_expression ']'
| direct_abstract_declarator '[' ']'
| direct_abstract_declarator '[' '*' ']'
| direct_abstract_declarator '[' STATIC type_qualifier_list assignment_expression ']'
| direct_abstract_declarator '[' STATIC assignment_expression ']'
| direct_abstract_declarator '[' type_qualifier_list assignment_expression ']'
| direct_abstract_declarator '[' type_qualifier_list STATIC assignment_expression ']'
| direct_abstract_declarator '[' type_qualifier_list ']'
| direct_abstract_declarator '[' assignment_expression ']'
| '(' ')'
| '(' parameter_type_list ')'
| direct_abstract_declarator '(' ')'
| direct_abstract_declarator '(' parameter_type_list ')'
;
initializer
: '{' initializer_list '}'
| '{' initializer_list ',' '}'
| assignment_expression
;
initializer_list
: designation initializer
| initializer
| initializer_list ',' designation initializer
| initializer_list ',' initializer
;
designation
: designator_list '='
;
designator_list
: designator
| designator_list designator
;
designator
: '[' constant_expression ']'
| '.' IDENTIFIER
;
static_assert_declaration
: STATIC_ASSERT '(' constant_expression ',' STRING_LITERAL ')' ';'
;
statement
: labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
labeled_statement
: IDENTIFIER ':' statement
| CASE constant_expression ':' statement
| DEFAULT ':' statement
;
compound_statement
: '{' '}'
| '{' block_item_list '}'
;
block_item_list
: block_item
| block_item_list block_item
;
block_item
: declaration
| statement
;
expression_statement
: ';'
| expression ';'
;
selection_statement
: IF '(' expression ')' statement ELSE statement
| IF '(' expression ')' statement
| SWITCH '(' expression ')' statement
;
iteration_statement
: WHILE '(' expression ')' statement
| DO statement WHILE '(' expression ')' ';'
| FOR '(' expression_statement expression_statement ')' statement
| FOR '(' expression_statement expression_statement expression ')' statement
| FOR '(' declaration expression_statement ')' statement
| FOR '(' declaration expression_statement expression ')' statement
;
jump_statement
: GOTO IDENTIFIER ';'
| CONTINUE ';'
| BREAK ';'
| RETURN ';'
| RETURN expression ';'
;
translation_unit
: external_declaration
| translation_unit external_declaration
;
external_declaration
: function_definition
| declaration
;
function_definition
: declaration_specifiers declarator declaration_list compound_statement
| declaration_specifiers declarator compound_statement
;
declaration_list
: declaration
| declaration_list declaration
;
%%
#include <stdio.h>
void yyerror(const char *s)
{
fflush(stdout);
fprintf(stderr, "*** %s\n", s);
}
void parse(FILE* fileInput)
{
yyin= fileInput;
while(feof(yyin)==0)
{
yyparse();// To read file, while() and yyparse() is necessary because we need to read until the content is run out
}
}
Обратите внимание, что: я подчеркивал соответствующие коды, которые относятся к моей проблеме комментарием:/*********************/
Когда Я собрал Лекса, это была не ошибка. Однако, когда я составил Yacc, я получил следующие сообщения:
2 rules never reduced
project.y: warning: 1 useless nonterminal and 2 useless rules
project.y:556.1-7: warning: useless nonterminal: include
project.y:557.3-31: warning: useless rule: include: '#' INCLUDE '<' STATEMENT '>'
project.y:558.3-31: warning: useless rule: include: '#' INCLUDE '"' STATEMENT '"'
Что мне делать, чтобы исправить эту проблему? И если возможно, не могли бы вы рассказать мне, почему я получил сообщения?
Может быть, потому что вы никогда не * использовать * в 'include' правило где-нибудь в парсер? –
Я не знаю, какой допотопный пример вы извлекли первые несколько вариантов lex, но все они устарели десятилетиями, а афайк не имеет никакого эффекта. Кроме того, каждый 'strdup', который вы выполняете, нуждается в соответствующем' free'; это большая работа, поэтому вам лучше не копировать какую-либо строку, если вы на самом деле не собираетесь использовать копию. Если вы никогда не собираетесь использовать семантическое значение, нет смысла хранить копию токена. Это почти наверняка имеет место для opetators и ключевых слов, поскольку вы уже знаете, как каждый из них пишется. – rici
Кажется, что существует основное неправильное понимание. в отношении: '#include <некоторая библиотека> или #include" некоторый заголовочный файл "' this '#include' is not true. Скорее, '< >' используется для файлов заголовков системы, а не для библиотек (хотя эти файлы заголовков могут содержать прототипы для функций в некоторой библиотеке) –
user3629249