首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Vczh Library++ 3.0 Parser Combinator 新增 def/let/binop 優化

     編輯:關於C語言

背景:ManagedX 語言的解析挑戰

ManagedX 有 5 種訪問修飾符(public, protected, private, internal, protected internal),前四者為單 Token,最後一個為 Tuple。需默認 private。舊組合子寫法冗長且需多個輔助函數。

新組合子:def 與 let

  • def(pattern, defaultValue):匹配成功返回 pattern 結果,失敗返回 defaultValue。
  • let(pattern, value):匹配成功返回 value,失敗則整體失敗。

組合使用,消除輔助函數:

// 舊寫法:需 ToAccessor, ToProtectedInternal, ToAccessorWithDefault 三個函數
accessor = (PUBLIC[ToAccessor] | PROTECTED[ToAccessor] | PRIVATE[ToAccessor] | INTERNAL[ToAccessor] | (PROTECTED+INTERNAL)[ToProtectedInternal])[ToAccessorWithDefault];

// 新寫法:一行搞定
accessor = def(
    let(PUBLIC, acc::Public) |
    let(PROTECTED, acc::Protected) |
    let(PRIVATE, acc::Private) |
    let(INTERNAL, acc::Internal) |
    let(PROTECTED+INTERNAL, acc::ProtectedInternal),
    acc::Private  // 默認值
);

新組合子:binop 解決表達式性能瓶頸

問題根源

通用 lrec 處理帶括號表達式時,每層括號增加一層文法遞歸。ManagedX 有 10+ 優先級,復雜表達式全加括號會導致數千層遞歸,虛函數調用開銷大。

binop 設計

手寫優先級解析器,通過流式 API 定義運算符表:

expression = binop(exp0)
    .pre(ADD_SUB, ToPreUnary).pre(NOT_BITNOT, ToPreUnary).pre(INC_DEC, ToPreUnary).precedence()
    .lbin(MUL_DIV_MOD, ToBinary).precedence()
    .lbin(ADD_SUB, ToBinary).precedence()
    .lbin(LT|LT, ToBinaryShift).lbin(GT|GT, ToBinaryShift).precedence()
    .lbin(LT, ToBinary).lbin(LE, ToBinary).lbin(GT, ToBinary).lbin(GE, ToBinary).precedence()
    .post(AS+type, ToCasting).post(IS+type, ToIsType).precedence()
    .lbin(EE, ToBinary).lbin(NE, ToBinary).precedence()
    .lbin(BITAND, ToBinary).precedence()
    .lbin(XOR, ToBinary).precedence()
    .lbin(BITOR, ToBinary).precedence()
    .lbin(AND, ToBinary).precedence()
    .lbin(OR, ToBinary).precedence()
    .lbin(QQ, ToNullChoice).precedence()
    .lbin(QT+(expression<
  • pre:前綴一元運算符(-a, ++i)。
  • post:後綴一元運算符(i++)。
  • lbin:左結合二元運算符(a+b+c)。
  • rbin:右結合二元運算符(a=b=c)。
  • precedence():分隔優先級層級。

性能提升

  • Debug 模式 100+ 倍,Release 模式略低。
  • 編譯速度依然碾壓 Boost.Spirit(秒級 vs 半小時)。

對比:舊 lrec 寫法

exp1 = exp0 | ((ADD_SUB | NOT_BITNOT | INC_DEC) + exp1)[ToUnary];
exp2 = lrec(exp1 + *((MUL_DIV_MOD + exp1)[ToBinaryLrec]), ToLrecExpression);
exp3 = lrec(exp2 + *((ADD_SUB + exp2)[ToBinaryLrec]), ToLrecExpression);
// ... 每層優先級一個 lrec

總結

def/let 簡化「可選匹配 + 默認值」模式,binop 以手寫優先級解析器替代通用左遞歸,解決了「括號炸彈」性能問題。Parser Combinator 重獲實用性能,同時保持極快編譯速度與聲明式風格。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved