我正在研究一個小型編譯器,以便更好地理解創建自己的語言的困難。現在我處於爲我的語法添加指針功能的階段,但我通過這樣做了減少/減少衝突。在我的語法中引入指針時減少/減少衝突
這是我的語法的簡化版本,可由bnfc
編譯。我使用happy
解析器生成器,這是程序告訴我存在減少/減少衝突。
entrypoints Stmt ;
-- Statements
-------------
SDecl. Stmt ::= Type Ident; -- ex: "int my_var;"
SExpr. Stmt ::= Expr; -- ex: "printInt(123); "
-- Types
-------------
TInt. Type ::= "int" ;
TPointer. Type ::= Type "*" ;
TAlias. Type ::= Ident ; -- This is how I implement typedefs
-- Expressions
--------------
EMult. Expr1 ::= Expr1 "*" Expr2 ;
ELitInt. Expr2 ::= Integer ;
EVariable. Expr2 ::= Ident ;
-- and the standard corecions
_. Expr ::= Expr1 ;
_. Expr1 ::= Expr2 ;
我正在學習語法如何工作的階段。但我想我知道會發生什麼。考慮這兩個方案
main(){
int a;
int b;
a * b;
}
和
typedef int my_type;
main(){
my_type * my_type_pointer_variable;
}
(該typedef
和main(){}
部分是不相關的,在我的語法,但是他們給予一定的上下文中)
在第一個節目,我想它會將a "*" b
解析爲Stmt ==(SExpr)==> Expr ==(EMult)==> Expr * Expr ==(..)==> Ident "*" Ident
,即基本上使用SExpr
規則開始步進。
與此同時,我想my_type * my_type_pointer_variable
使用規則進行擴展。 Stmt ==(SDecl)==> Type Ident ==(TPointer)==> Type "*" Ident ==(TAlias)==> Ident "*" Ident
。
但是,語法階段不知道標識符最初是一個類型別名還是變量。 (1)我怎樣才能擺脫減少/減少衝突和(2)我是唯一有這個問題的人嗎?有沒有一個明顯的解決方案,c語法如何解決這個問題?
到目前爲止,我已經成功地通過使用「&」或其他符號而不是「*」成功地更改了我的語言的語法,但這是非常不可取的。另外,我不能從各種公共C語法中理解,並試圖明白爲什麼他們沒有這個問題,但我沒有在這方面運氣。
最後,我該如何自行解決這些問題?我從happy
得知的更詳細的輸出是衝突發生的方式,是巧妙解決這些衝突的唯一方法嗎?恐怕我會偶然發現更多的問題,例如介紹EIndir. Expr = '*' Expr;
非常有趣!有沒有辦法做到這一點,而不用編寫自己的不需要有內存的詞法分析器?或者是否真的沒有類似c語法的編程語言(使用'*'乘法*和*指針聲明),並允許將類型別名聲明(typedefs)放在代碼中的任何位置? – Tarrasch
現在標記爲正確。我剛剛意識到,詞法分析黑客是一個實際的術語,甚至在維基百科上進行了解釋。我編輯了答案,清楚地反映了這一點。 – Tarrasch