我已经准备好了扫描器和解析器,使用flex和bison。
解析器直接在动作中构建树,为此,我创建了一个名为STreeNode的结构体,并使用
#define YYSTYPE_IS_DECLARED
typedef STreeNode* YYSTYPE;
结构体为:
typedef struct tagSTreeNode
{
EOperationType type;
int count;
struct tagSTreeNode **children;
char *string;
} STreeNode;
大概有40个标记,对于每个规则我都有类似
的东西unlabeled_statement:
assignment {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
| function_call_statement {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
| goto {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
| return {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
| conditional {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
| repetitive {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
| empty_statement {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);}
;
createNode函数的签名是
STreeNode *createNode(EOperationType type, int count, ...) {
树工作得很好。问题是访问变量名、函数名等的真实值。由于YYSTYPE是一个结构体,$x没有我想保存在结构体中的char * string元素上的字符串值。
我有一个名为IDENTIFIER的%令牌和另一个名为INTEGER的%令牌,它们应该接收到我想要的值。
通过研究,我发现我可以尝试使用联合{}来获得特定类型的每个令牌。也许这能帮上忙?如果是这样,我就必须为每个令牌指定类型吗?如何实现呢?yytext呢?难道不能用它来实现这个目标吗?
谢谢!
—EDIT—
所以我创建了
%union {
char *string;
STreeNode *node;
}
并指定每个终端和非终端类型为其中之一。节点仍在工作,但使用的字符串(例如$1)返回null。
我还需要更改扫描仪中的任何东西吗?我的扫描仪有:
[a-zA-Z][a-z0-9A-Z]* { return IDENTIFIER; }
[0-9]+ { return INTEGER; }
再次感谢。
如果您的令牌为它们设置了类型,则词法分析器需要将yylval
设置为所讨论的类型。比如:
[a-zA-Z][a-z0-9A-Z]* { yylval.string = strdup(yytext); return IDENTIFIER; }
[0-9]+ { yylval.string = strdup(yytext); return INTEGER; }