我正在研究用於描述UI小部件的簡單玩具語言。我用bison/flex來實現語法。我現在想從語法規則中創建一個AST。但是,我不確定AST的「粒度級別」以及它應該包含哪些內容。從我所讀到的,AST應該是「最小的」,並避免提供冗餘信息。同時顯然我不應該放棄原始資料中的任何信息。構建AST時是否有特定的規則?構建抽象語法樹時需要考慮的要點
的語法如下:
%{
#include <string>
#include <iostream>
void yyerror (const char *error);
int yylex();
extern int yylineno;
%}
%code{
// int lineno;
}
%union {
char* s;
double d;
int i;
}
/* declare tokens */
%token APPLICATION GEOMETRY
%token FORM BUTTON LABEL TEXTINPUT
%token ID NAME
%token WIDTH HEIGHT TEXT ONCLICK
%token ABSOLUTELAYOUT LINEARLAYOUT GRIDLAYOUT
%token ABSOLUTE_LAYOUT_DOT_LEFT ABSOLUTE_LAYOUT_DOT_TOP
%token EOL ENDOFFILE
%token<s> IDENTIFIER STRING
%token<d> INTEGER
%%
appDef: APPLICATION '{' NAME ':' STRING formdefList '}' {std::cout << "found app" << std::endl;}
iddef : ID ':' IDENTIFIER
formdefList : /* nothing */
| formdefList formdef
;
formdef : FORM '{' formbodydef '}'
;
formbodydef : /*nothing*/
| iddef
| formbodydef layoutdef
| error {
std::cout << "found error in form body near line: " << yylineno << std::endl;
std::exit(1);
}
;
layoutdef : ABSOLUTELAYOUT '{' layoutBody '}'
| GRIDLAYOUT '{' layoutBody '}'
| LINEARLAYOUT '{' layoutBody '}'
;
layoutBody : /* nothing */
| layoutBody layoutdef /* Layouts can be embedded in one another */
| layoutBody buttonDef
| layoutBody labelDef
| error { std::cout << "Was expecting a child control near line: " << yylineno << std::endl; std::exit(1);}
;
geometrydef : GEOMETRY ':' '{' geometrybody '}' { std::cout << "start of geometry def:" << std::endl;}
;
geometrybody : /*nothing*/ { std::cout << "start of geometrybody def" << std::endl;}
| geometrybody WIDTH ':' INTEGER
| geometrybody HEIGHT ':' INTEGER
| geometrybody ABSOLUTE_LAYOUT_DOT_LEFT ':' INTEGER
| geometrybody ABSOLUTE_LAYOUT_DOT_TOP ':' INTEGER
| error { std::cout << "error near line: " << yylineno << std::endl; std::exit(1);}
;
buttonDef : BUTTON '{' buttonBody '}'
;
buttonBody : /*nothing*/
| buttonBody iddef
| buttonBody TEXT ':' STRING
| buttonBody geometrydef
;
labelDef : LABEL '{' labelBody '}'
;
labelBody : /*nothing*/
| labelBody iddef
| labelBody TEXT ':' STRING
| labelBody geometrydef
;
%%
void yyerror (const char *error)
{
std::cout << error << std::endl;
}
下面是驗證一些語法樣品輸入:
Application{
name: "HelloWorld"
Form{
id: MainForm
LinearLayout{
Button{
geometry: {width:20 height:20}
}
AbsoluteLayout{
Button{
geometry:{
width:20
height:20
AbsoluteLayout.Top:10
AbsoluteLayout.Left:20
}
}
}
}
}
Form{
id: Secondary
}
}
我現在是在建立一個AST的語法的過程中,需要一些對其結構的建議:
- 我應該如何將語法規則映射到AST節點?每個終端符號有一個AST節點?
- 我應該如何設計節點之間的父子關係?
- 文法規則的左手邊是否明確出現在AST中,如
formdef
,formbodydef
,formdefList
? - 我應該在節點中包含什麼?簡單地包括終端令牌類型(
ID
,NAME
等)和令牌值是否足夠? - 我是否應該將所有標記值包含爲字符串,並在稍後階段執行實際類型轉換(如字符串到整數等)?
感謝您的諮詢!
在有人抱怨這個答案包含「主要」鏈接(一個重複的SO口頭禪:「它可以在因特網上陳舊因此在這裏複製一切」),讓我注意到這些鏈接* stackoverlow *。只有在stackoverflow消失時它們纔會陳舊。鏈接的關鍵是避免製作完美信息的副本,創建難以維護的克隆。 –
感謝您的解釋和參考鏈接。這非常有幫助! – BigONotation
@IraBaxter看到我的評論[這裏](http://stackoverflow.com/a/6320259/207421)關於轉換的站點。 – EJP