我需要一些关于野牛语法结构的帮助。
从我的另一个问题:
我正在尝试编写一个元语言来编写标记代码(比如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源代码中,不必使用prints,每个返回语句都将用于输出(在printf函数中)。
程序的输出将是干净的html代码。
因此,例如,标题1标记的转换如下:
h1 { "Hello, " + toCapital(name) + "!"; }
// would become:
printf("<h1>Hello, %s!</h1>", toCapital(name));

我的主要目标是创建一个解释器,将wdi源代码转换为html,如下所示:
tag(attributes) {content}=><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代码时我刚开始学习语言处理技术,所以我需要一些指导。
有人能纠正我的代码或给出一些例子什么是正确的方法来解决这个问题吗?

最佳答案

如果您的意图是解析C代码和嵌入的WDI代码,那么您将遇到一个困难LALR(1)解析器生成器(包括Bison)在解析C方面是出了名的糟糕,更不用说比C更复杂的事情了(意味着C+WDI)。
或者你必须:
a)学习如何通过混合解析和符号表构造使Bison解析C(也就是说,与GNU-GCC斗争看看他们是如何做到的),
b)切换到更强大的语法分析器生成器,如GLR语法分析器生成器(Bison可以选择使用GLR语法分析器生成器),并学习如何处理不明确的语法以及如何解决它们,

c)将WDI设计为一种岛国语法,其目标是挑选出WDI代码,并将所有非WDI的内容保留为不透明字符串(在您的情况下,注定要输出为假定的c代码)后一种方法简单得多,大致上是所有网页语言(ASP、PHP、JSP…)所做的好处是这样做容易得多,而且您只需为WDI本身编写语法,并使用一个lexer将所有不属于WDI的内容提取为一个abitrary字符串缺点是你不能让WDI和C很好地交互/和/或用你的解析器检查WDI程序的有效性。
有关更多背景信息,请参见此问题:
Island grammar antlr3
如果在开始此项目之前更详细地了解编译器技术,这将更容易。

10-08 13:02