Предупреждения lex и yacc не работают должным образом
Lexer.l
%{
#include "y.tab.h"
%}
%%
"define" return(TK_KEY_DEFINE);
"as" return(TK_KEY_AS);
"is" return(TK_KEY_IS);
"if" return(TK_KEY_IF);
"then" return(TK_KEY_THEN);
"else" return(TK_KEY_ELSE);
"endif" return(TK_KEY_ENDIF);
"with" return(TK_KEY_WITH);
"DEFINE" return(TK_KEY_DEFINE_UC);
"AS" return(TK_KEY_AS_UC);
"IS" return(TK_KEY_IS_UC);
"IF" return(TK_KEY_IF_UC);
"THEN" return(TK_KEY_THEN_UC);
"ELSE" return(TK_KEY_ELSE_UC);
"ENDIF" return(TK_KEY_ENDIF_UC);
"WITH" return(TK_KEY_WITH_UC);
"+" return(TK_PLUS);
"-" return(TK_MINUS);
"*" return(TK_MUL);
"/" return(TK_DIV);
"~" return(TK_NOT);
"&" return(TK_AND);
"|" return(TK_OR);
"<=" return(TK_LEQ);
"<" return(TK_LESS);
">=" return(TK_GEQ);
">" return(TK_GT);
"==" return(TK_EQ);
"=" return(TK_ASSIGN);
"(" return(TK_OPEN);
")" return(TK_CLOSE);
";" return(TK_SEMI);
"," return(TK_COMMA);
[[:alpha:]_][[:alnum:]_]* return(IDENTIFIER);
[+-]?[0-9]+ return(INTEGER);
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+) return(REAL);
[[:space:]]+ ;
%%
int yywrap(void)
{
return 1;
}
Parser.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
struct node *left;
struct node *right;
char *token;
} node;
node *mknode(node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%start Program
%token TK_KEY_DEFINE TK_KEY_DEFINE_UC
%token TK_KEY_AS TK_KEY_AS_UC
%token TK_KEY_IS TK_KEY_IS_UC
%token TK_KEY_IF TK_KEY_IF_UC
%token TK_KEY_THEN TK_KEY_THEN_UC
%token TK_KEY_ELSE TK_KEY_ELSE_UC
%token TK_KEY_ENDIF TK_KEY_ENDIF_UC
%token TK_KEY_WITH TK_KEY_WITH_UC
%token TK_PLUS TK_MINUS
%token TK_MUL TK_DIV
%token TK_NOT
%token TK_AND
%token TK_OR
%token TK_LEQ TK_LESS TK_GEQ TK_GT
%token TK_EQ
%token TK_ASSIGN
%token TK_OPEN TK_CLOSE
%token TK_SEMI
%token TK_COMMA
%token IDENTIFIER
%token INTEGER
%token REAL
%left TK_PLUS TK_MINUS
%left TK_MUL TK_DIV
%left TK_LEG TK_LESS TK_GEQ TK_GT
%left TK_AND TK_OR
%left TK_EQ
%right TK_NOT TK_ASSIGN
%%
Program : Macros Statements;
Macros : /* empty */
| Macro Macros
;
Macro : TK_KEY_DEFINE MacroTemplate TK_KEY_AS Expression;
MacroTemplate : IDENTIFIER MT;
MT : /*empty*/
| TK_OPEN IdentifierList TK_CLOSE
;
IdentifierList : IDENTIFIER I;
I : /*empty*/
| TK_COMMA IdentifierList
;
Statements : /*empty*/
| Statement Statements
;
IfStmt : TK_KEY_IF Condition TK_KEY_THEN Statements TK_KEY_ELSE Statements TK_KEY_ENDIF;
Statement : AssignStmt
| IfStmt
;
AssignStmt : IDENTIFIER TK_KEY_IS Expression;
Condition : C1 C11;
C11 : /*empty*/
| TK_OR C1 C11
;
C1 : C2 C22;
C22 : /*empty*/
| TK_AND C2 C22
;
C2 : C3 C33;
C33 : TK_EQ C3 C33;
C3 : C4 C44;
C44 : /*empty*/
| TK_LESS C4 C44
| TK_LEQ C4 C44
| TK_GT C4 C44
| TK_GEQ C4 C44
;
C4 : TK_NOT C5 | C5;
C5 : INTEGER | REAL | TK_OPEN Condition TK_CLOSE;
Expression : Term EE;
EE : /*empty*/
| TK_PLUS Term EE
| TK_MINUS Term EE
;
Term : Factor TT;
TT : /*empty*/
| TK_MUL Factor TT
| TK_DIV Factor TT
;
Factor : IDENTIFIER | REAL | INTEGER | TK_OPEN Expression TK_CLOSE;
%%
int main (void) {return yyparse ( );}
node *mknode(node *left, node *right, char *token)
{
/* malloc the node */
node *newnode = (node *)malloc(sizeof(node));
char *newstr = (char *)malloc(strlen(token)+1);
strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
void printtree(node *tree)
{
int i;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
int yyerror (char *s)
{
fprintf (stderr, "%s\n", s);
}
Я желаю вывод в дерево разбора, если нет ошибок и указать ошибки, если таковые имеются. Но я получаю много предупреждений, таких как
warning: rule useless in grammar
warning: nonterminal useless in grammar
Я понял причину этого, прочитав другие подобные вопросы, но не смог исправить это сам. Пожалуйста, помогите мне решить это. Спасибо!
Привет Ричи,
Большое вам спасибо, так что мне не нужно беспокоиться о левой рекурсии, левой факторизованной грамматике и т. Д., И вы можете использовать что-то вроде ниже в yacc?
%%
Program : Macros Statements;
Macros : /*empty*/
|Macro Macros
;
Macro : TK_KEY_DEFINE MacroTemplate TK_KEY_AS Expression;
MacroTemplate : VarTemplate
| FunTemplate
;
VarTemplate : IDENTIFIER;
FunTemplate : IDENTIFIER TK_OPEN IdentifierList TK_CLOSE;
IdentifierList : IDENTIFIER TK_COMMA IdentifierList
| IDENTIFIER
;
Statements : /*empty*/
| Statement Statements
;
IfStmt : TK_KEY_IF Condition TK_KEY_THEN Statements TK_KEY_ELSE Statements TK_KEY_ENDIF;
Statement : AssignStmt
| IfStmt
;
AssignStmt : IDENTIFIER TK_KEY_IS Expression;
Condition : Condition TK_AND Condition
| Condition TK_OR Condition
| Condition TK_LESS Condition
| Condition TK_LEQ Condition
| Condition TK_GT Condition
| Condition TK_GEQ Condition
| Condition TK_EQ Condition
| TK_NOT Condition
| TK_OPEN Condition TK_CLOSE
| INTEGER
| REAL
;
Expression : Expression TK_PLUS Expression
| Expression TK_MINUS Expression
| Expression TK_MUL Expression
| Expression TK_DIV Expression
| TK_OPEN Expression TK_CLOSE
| IDENTIFIER
| INTEGER
| REAL
;
%%
Также да, я отметил ваш последний пункт:)
1 ответ
В отличие от C11
, C22
, C44
и другие "хвостовые" правила, которые могут произвести %empty
, C33
имеет только одну продукцию:
C33 : TK_EQ C3 C33;
Поскольку он не имеет нерекурсивного производства, он не может создать предложение (состоящее только из нетерминалов). И так как это часть единственного производства для C2
которая является частью единственного производства для C1
которая является частью единственного производства для Condition
которая является частью единственного производства для IfStmt
ни один из них не может дать ни одного предложения. Правило, которое не может привести ни к какому предложению, технически описывается как "бесполезное", а нетерминальное, все правила которого бесполезны (или единственное правило которого бесполезно), является "бесполезным нетерминалом".
Есть еще одна категория бесполезных нетерминалов: те, которые не могут быть созданы никаким полезным правилом. Это будет в случае с C4
(который может быть произведен только C3
который был обнаружен бесполезным) и, таким образом, с C44
а также C5
,
Должно быть очевидно, как это исправить, но я хотел бы отметить, что вы завязываете себя в узлы, пытаясь избежать левой рекурсии, которая является ненужной и непродуктивной при использовании восходящего генератора синтаксического анализатора, такого как бизон / Yacc. (См. Последний абзац этого ответа для более длительного ворчания по этому поводу.) Искусственные произведения (C33
и друзья) служат только для усложнения разбора дерева.
Кроме того, поскольку ваша грамматика не является неоднозначной - в сущности, правила производства четко определяют сильные стороны привязки операторов - различные объявления приоритетов не имеют смысла. (В отличие от "бесполезного", это не технический термин:-)). Декларации предшествования применяются только для разрешения грамматической неоднозначности, которой здесь нет.
Наконец, я думаю, что вы должны пересмотреть свою грамматику для Condition
s. В чем, например, смысл ~3 < ~4
? И почему x * 2 < y
недействительный?