我正在尝试为一种格式化语言编写一个编译器。这种语言有一个开始和结束属性以及一组文档和文本属性。第一个只是文档本身的信息,而第二个是实际文档(标题,段落,列表......通常)。第一个集合必须始终遵循 start 属性,并且必须包含所有属性,但按用户可能喜欢的任何顺序。
假设我的属性标记是 PROP1、PROP2、PROP3 和 PROP4,我可以对所有属性使用递归和 OR,以便用户可以定义他想要的任何文档属性。
doc_properties
: /* empty */
: doc_properties property
;
property
: PROP1
: PROP2
: PROP3
: PROP4
;
但是我如何让他定义它们,而且只定义一次。我认为的一种方法(我想避免的简单而粗暴的方法)是因为我只有 4 个文档属性,我可以制作一个或所有可能的组合。我很确定还有另一种方法。有什么帮助吗?
到目前为止,我的语法非常简单而且很小
%{ /* C Stuff */ %}
/* union and error stuff and tokens */
%%
source
: /* empty */
| entry_point doc_properties txt_properties exit_point
;
entry_point
: SLASH BLOCK_S LBRACE DOC RBRACE
;
doc_properties
: /* This is where my question goes */
;
txt_properties
: /* empty */
;
exit_point
: SLASH BLOCK_E LBRACE DOC RBRACE
;
%%
int main (int argc, char* argv[])
{
/* various checks for the arguments and the input output files */
yyin = fopen(argv[1], "r");
yyout = fopen(fn, "w");
//do{
yyparse();
//}while(!feof(yyin));
fclose(yyin);
fclose(yyout);
return 0;
}
void yyerror(const char* str) {
fprintf(stderr,"syntax error[%d]: %s\n",yylineno, str);
}
同样在不相关的注释中,在 do-while 循环中使用 yyparse() 或仅使用一次本身有什么区别吗?因为我看到它是双向的,而 do-while 循环对我来说更有意义(因为它请求一个令牌解析然后再次)我不确定该函数是否重复自身或什么......