尝试过3种思路,最后才写出一个满意的推导式。
支持带id和省略id的写法。
如:
long int * ( * id ) ()
也支持省略id,即 long int * ( * ) () ,这也会被视为一个合乎语法的串,从语义上再根据上下文来决定缺省id是否合乎语义就可以了。
先将 c 的类型声明先分为2个部分,前置类型段和符号声明段。再将符号声明段分为3个部分。
接上例:
前置类型段为: long int
符号声明段,其中:
前段: *
中段: (*id)
后段: ()
前置类型段推导式为:
TDcl = SU
| Enum
| Types
| const TDcl
| TDcl const
SU是指以struct union关键字开始的文法, Enum是enum关键字开始的文法,const是终结符,指const或volatile
这样,TDcl就会将直到 * ( [ id 前的符号归结。
如 int const , struct XXX { int a; } const volatile
符号声名段的文法如下:
NDcl = NDclPr
| NDclPr NDclMd
| NDclPr NDclMd NDclBk
符号声明段可以是: 只有前段 或 前段+中段 或 三段都有。
这三种情况分别对应: int const | int const * | int const *id [10]
三段的文法为:
NDclPr = mul
| NDclPr mul
| NDclPr const
NDclMd = id
| bl NDcl br
NDclBkI= kl kr
| kl Expr kr
| bl br
| bl FPS br
NDclBk = NDclBkI
| NDclBk NDclBkI
其中,mul就是指*号, FPS是形式参数的文法:
FPSI = TDcl
| TDcl NDcl
FPS = FPSI
| FPS comma FPSI
| FPS comma dot3
(comma 是 符号 , (逗号) , dot3 是 ... (不定长参数) )