我需要一些关于野牛语法构建的帮助。
从我的另一个问题: 我正在尝试编写一种用于编写标记代码的元语言(例如xml和html),它可以直接嵌入到C / C ++代码中。 这是一个用这种语言编写的简单示例,我称之为WDI(Web开发接口):
/*
* Simple wdi/html sample source code
*/
#include <mySite>
string name = "myName";
string toCapital(string str);
html
{
head {
title { mySiteTitle; }
link(rel="stylesheet", href="style.css");
}
body(id="default") {
// Page content wrapper
div(id="wrapper", class="some_class") {
h1 { "Hello, " + toCapital(name) + "!"; }
// Lists post
ul(id="post_list") {
for(post in posts) {
li { a(href=post.getID()) { post.tilte; } }
}
}
}
}
}
基本上它是一个C源代码,具有用户友好的html界面。 正如您所看到的那样,传统的基于标签的样式被类似C的样式替换,其中的块由花括号分隔。 我需要构建一个解释器来将此代码转换为html,然后将其插入到C中,以便可以编译它。 C部分保持不变。 在wdi源代码内部没有必要使用print,每个return语句都将用于输出(在printf函数中)。 该程序的输出将是干净的HTML代码。
因此,例如标题1标签将被转换为:
h1 { "Hello, " + toCapital(name) + "!"; }
// would become:
printf("<h1>Hello, %s!</h1>", toCapital(name));
我的主要目标是创建一个解释器,将wdi源转换为html,如下所示:
tag(attributes) {content}
=&gt; <tag attributes>content</tag>
其次,解释器返回的html代码必须用printfs插入到C代码中。 wdi中发生的变量和函数也应该进行排序,以便将它们用作printf参数(样本源中的toCapital(name)的情况)。
以下是我的flex / bison文件:
id [a-zA-Z_]([a-zA-Z0-9_])*
number [0-9]+
string \".*\"
%%
{id} {
yylval.string = strdup(yytext);
return(ID);
}
{number} {
yylval.number = atoi(yytext);
return(NUMBER);
}
{string} {
yylval.string = strdup(yytext);
return(STRING);
}
"(" { return(LPAREN); }
")" { return(RPAREN); }
"{" { return(LBRACE); }
"}" { return(RBRACE); }
"=" { return(ASSIGN); }
"," { return(COMMA); }
";" { return(SEMICOLON); }
\n|\r|\f { /* ignore EOL */ }
[ \t]+ { /* ignore whitespace */ }
. { /* return(CCODE); Find C source */ }
%%
%start wdi
%token LPAREN RPAREN LBRACE RBRACE ASSIGN COMMA SEMICOLON CCODE QUOTE
%union
{
int number;
char *string;
}
%token <string> ID STRING
%token <number> NUMBER
%%
wdi
: /* empty */
| blocks
;
blocks
: block
| blocks block
;
block
: head SEMICOLON
| head body
;
head
: ID
| ID
attributes
;
attributes
: LPAREN RPAREN
| LPAREN attribute_list RPAREN
;
attribute_list
: attribute
| attribute COMMA attribute_list
;
attribute
: key ASSIGN value
;
key
: ID {$$=$1}
;
value
: STRING {$$=$1}
/*| NUMBER*/
/*| CCODE*/
;
body
: LBRACE content RBRACE
;
content
: /* */
| blocks
| STRING SEMICOLON
| NUMBER SEMICOLON
| CCODE
;
%%
我在为语言定义正确的语法时遇到了困难,特别是在拆分WDI和C代码时。我刚开始学习语言处理技术,所以我需要一些方向。 有人可以更正我的代码或提供一些解决此问题的正确方法的例子吗?
答案 0 :(得分:2)
如果您的目的是解析 C代码和嵌入式WDI代码,那么您将陷入困境。 LALR(1)解析器生成器(包括Bison)在解析C时非常糟糕,更不用说比C更复杂的东西(意思是C + WDI)。
要么你必须:
a)学习如何通过纠结解析和符号表构造来使Bison解析C(意思是,与GNU GCC斗争以了解他们是如何做到的),
b)切换到更强大的解析器生成器,例如GLR解析器生成器(Bison有一个选项),并学习如何处理模糊语法以及如何解决它们,
或
c)将WDI设计为一种岛语法,其目标是选择WDI代码并将不是WDI的所有内容保留为不透明字符串(在您的情况下,注定要输出为假定的C代码)。后一种方法更容易,并且大致是所有网页语言(ASP,PHP,JSP ...)的功能。好处是,这更容易,你只需要为WDI本身写一个语法,并且一个词法分析器将把所有不是WDI的东西作为一个abitrary字符串。缺点是你不能使WDI和C很好地交互/和/或用你的解析器检查WDI程序的有效性。 有关更多背景,请参阅此SO问题:如果您在开始此项目之前更详细地了解编译器技术,这会更容易。