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
我通过阅读其他类似的问题来理解这一点,但我自己无法纠正。请帮我解决这个问题。谢谢!
嗨rici,
非常感谢你,所以我不必担心左递归,左会计语法等,并直接继续在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
;
%%
同样是的,我注意到你的最后一点:)
答案 0 :(得分:1)
与C11
,C22
,C44
和其他&#34; tail&#34;不同。规则,可以产生%empty
,C33
只有一个产品:
C33 : TK_EQ C3 C33;
由于它没有非递归产生,因此不可能产生一个句子(仅由非终端组成)。并且因为它是C2
的唯一产品的一部分,C1
是Condition
的唯一产品的一部分,IfStmt
是C4
的唯一产品的一部分,C3
是C44
的唯一产品的一部分{1}},这些都不会产生任何句子。不能产生任何句子的规则在技术上被描述为&#34;无用的&#34;所有规则都无用(或者其唯一规则无用)的非终端是一个无用的非终端&#34;。
还有另一类无用的非终端:无法通过任何有用规则生成的终端。 C5
就是这种情况(只能由C33
生成,已被发现无效),因此Condition
和~3 < ~4
也是如此。
应该明白如何解决这个问题,但是我想指出你是通过试图避免左递归而将自己捆绑在一起,这在使用自下而上时既不必要又适得其反解析器生成器,如bison / yacc。 (请参阅this answer的最后一段,了解更长时间的抱怨。)人工制作(x * 2 < y
和朋友)仅用于使解析树复杂化。
此外,由于您的语法不明确 - 实际上,生产规则明确定义了运算符绑定强度 - 各种优先级声明都没有意义。 (与&#34;无用的&#34;不同,这不是技术术语:-))。优先级声明仅适用于解决语法歧义,此处不存在。
最后,我认为你应该重新审视UIImageView
的语法。例如,UIView
的含义是什么?为什么FormatException
无效?