2012-04-12 56 views
2

如果前視標記是給定值,是否有方法可以指定Bison規則不應該匹配?野牛拿起C函數指針作爲函數調用?

我公司目前有以下野牛語法(簡體):

var_decl: 
     type ident 
     { 
      $$ = new NVariableDeclaration(*$1, *$2); 
     } | 
     type ident ASSIGN_EQUAL expr 
     { 
      $$ = new NVariableDeclaration(*$1, *$2, $4); 
     } | 
     type CURVED_OPEN STAR ident CURVED_CLOSE CURVED_OPEN func_decl_args CURVED_CLOSE 
     { 
      $$ = new NVariableDeclaration(*(new NFunctionPointerType(*$1, *$7)) /* TODO: free this memory */, *$4); 
     } | 
     type CURVED_OPEN STAR ident CURVED_CLOSE CURVED_OPEN func_decl_args CURVED_CLOSE ASSIGN_EQUAL expr 
     { 
      $$ = new NVariableDeclaration(*(new NFunctionPointerType(*$1, *$7)) /* TODO: free this memory */, *$4, $10); 
     } ; 

... 

deref: 
     STAR ident 
     { 
      $$ = new NDereferenceOperator(*$<ident>2); 
     } | 

... 

type: 
     ident 
     { 
      $$ = new NType($<type>1->name, 0, false); 
      delete $1; 
     } | 
     ... ; 

... 

expr: 
     deref 
     { 
      $$ = $1; 
     } | 
     ... 
     ident 
     { 
      $<ident>$ = $1; 
     } | 
     ... 
     ident CURVED_OPEN call_args CURVED_CLOSE 
     { 
      $$ = new NMethodCall(*$1, *$3); 
      delete $3; 
     } | 
     ... 
     CURVED_OPEN expr CURVED_CLOSE 
     { 
      $$ = $2; 
     } ; 

... 

call_args: 
     /* empty */ 
     { 
      $$ = new ExpressionList(); 
     } | 
     expr 
     { 
      $$ = new ExpressionList(); 
      $$->push_back($1); 
     } | 
     call_args COMMA expr 
     { 
      $1->push_back($3); 
     } ; 

的問題是,在解析時:

void (*ident)(char* some_arg); 

它看到無效(* IDENT),並推斷出它必須是一個函數調用而不是函數聲明。 有沒有一種方法可以告訴Bison它應該有利於展望匹配var_decl而不是將* ident和void減少爲derefs和exprs?

+0

你沒有講完整個故事。在你的語法中,表達式不能以類型開始。它是如何從表達式開始的? – 2012-04-12 21:35:18

+0

我已經添加了'type'的語法;正如你所看到的,任何標識符都可以是一個類型。我沒有發佈整個語法的原因是它的長度爲520行,可能會嚇跑人們:P – 2012-04-12 21:48:47

+1

您可能需要查看C++的「最煩人的分析」。在那裏有一條規則,如果某件事可以成爲一種聲明,那就是這樣。 – 2012-04-12 22:00:38

回答

3

任何標識符可以是類型

這正是這個問題。類似C語言的LALR(1)語法(或類型爲C類語法的語言)需要在令牌級別區分類型和其他標識符。也就是說,你需要IDENT和TYPEIDENT是兩個不同的標記。 (您必須將有關標識符的數據從編譯器反饋回標記器)。這是消除模糊語法的最標準方法。

更新例如參見this ANSI C grammar for Yacc

+0

謝謝!事後看來,實際上讓安靜有點意義,它必須這樣做:) – 2012-04-12 22:35:09