2012-07-01 44 views
5

Operatörlerin Menhir ayrıştırıcısını (Ocamlyacc benzeri) kullanarak dinamik özniteliklere (öncelik ve öncelik) sahip olduğu bir dili ayrıştırmaya çalışıyorum. Lexing fazı boyunca, tüm operatörler bir OP:string belirtecini doldururlar (böylece "+" (OP "+"), vs'ye dönüşür).Menhir/Ocamlyacc içindeki bir işleç için bir dinamik öncelik ve önceliğin belirtilmesi

Operatör öznitelikleri ayrıştırma saatine göre belirlenir ve operatörleri ilişkilendiren bir tabloyu ve özelliklerini özetler. Bu tablo göz önüne alındığında, Menhir'e bu tablonun verilerine dayanarak operatörleri ayrıştırma kuralının önceliğini dinamik olarak değiştirmesini nasıl öğretebilirim?

Teşekkürler, CharlieP.

cevap

10

"Yanlış yapıyorsunuz" türden bir yorum ile yanıtladığınız için üzgünüm. Ben umut üç itirazlar alaka azalan sırada, yapıcı vardır:

  1. Menhir dinamik dilbilgisi güncellemeleri için verilmemiştir; Dilbilgisini ayrıştırma zamanında değiştirmekte ısrar ederseniz, bu özelliği sağlayan bir araç kullanmalısınız, örneğin GLR çözümleyici Dypgen. Dypgen kılavuzu, operatör önceliklerini, kısıtlı bir şekilde (yeni operatörler ve ilgili öncelikleri ekleyebileceğiniz, ancak var olanların önceliklerini değiştiremeyeceğiniz gibi) ihtiyaçlarınızı karşılayabilecek veya uymayabilecek dinamik bir şekilde güncelleme olasılığından bahseder. Dypgen manual (PDF), sayfa ... 'a bakın. 42.

  2. Bir CFG dilbilgisinin dinamik olarak güncellenmesi, kullanıcı tanımlı operatör önceliklerini işlemenin en iyi yolu değil, bence. Agda, çok genel kullanıcı tanımlı mikser operatörlerine sahiptir ve bunların çözümü kabaca aşağıdaki gibidir: CFG çözümleyicinizi, statik olarak bilinen dilbilgisel yapıyı ayrıştırmak için kullanın, ancak fantezi öncelikleri ve ilişkilendirmeleri kullanabilen ifadeler için bunları yalnızca bir listeye ayırın. belirteçleri. Örneğin, let x = if foo then x + y * z else bar, Let(x, If(foo, Expr(x, +, y, *, z), bar) gibi bir şeye ayrıştırılabilir. Daha sonraki bir uzmanlık geçişi, gerekli bilgileri özel yapılarına Expr düğümlerine ayrıştırmak için gerekli bilgileri toplayabilir. Parser jeneratörler için iyi olduklarını (statik olarak bilinen zengin CFG) kullanın ve karmaşık, kötü tanımlanmış, dinamik şeyler için bir son işleme geçişi kullanın. Agda adamlarının konuyla ilgili bazı literatürleri var, örneğin, Parsing Mixfix Operators, Danielsson ve Norell, 2009.

    Tasarım açısından, lexing'inizi birbirinden ayırmanızı ve her biri iyi bir şekilde birkaç farklı geçişte ayırmanızı şiddetle tavsiye ederim. - Kendi davranışlarını dinamik olarak değiştirmeye çalışmak yerine, yalnızca önceki yapıda toplanan bilgileri kullanır ve kullanır. Daha basit ve çok daha sağlam bir şeye sahip olacaksınız.

  3. Dinamik veya kullanıcı tanımlı öncelik ve öncelikler bence, biraz kötülüktür. OCaml, operatörün öncelik önceliklerinin ilk birkaç karakterine göre belirlendiği farklı bir sisteme sahiptir (örn. @, @@ ve @+ hepsi doğru-ilişkilendiricidir). Bir infix operatörünü seçen insanlar için biraz kısıtlayıcıdır, ancak okuyucuyu okuyucuyu çok daha rahat yaşayabilir, çünkü gözlerini herhangi bir yeni parça koduna dinamik olarak adapte etmek yerine, sadece bir dizi gramer kuralları vardır. . Tamamen farklı bir sözdizimi ile yabani, yabancı kod parçalarının yerleştirilmesine izin vermek istiyorsanız, teklif mekanizmaları (örn. Camlp4 <:foo<...>>), operatör seviyesindeki ilişkilendirmeler ve önceliklerle uğraşmaktan çok daha sağlamdır ve ayrıştırılması daha kolaydır.

    Bu, projelerin farklı gereksinimlere sahip olduğunu ve benim bilmediğim bazı uygulamalar için işlevselliklerin önceliklerini ve ilişkilendirmelerini dinamik olarak değiştirmekte ısrar edip etmediğinizi tamamen anlayabileceğimi söyledi.Sadece bunun tek yol olmadığını ve bazen tutarlılık ve sadeliğin mutlak esneklikten daha iyi olduğunu unutmayın.