سؤال

وأنا أحاول في contruct محلل في سكالا التي يمكن تحليل السلاسل-SQL مثل بسيطة. لقد حصلت على أساسيات العمل ويمكن تحليل شيئا مثل:

select id from users where name = "peter" and age = 30 order by lastname

ولكن الآن أنا أتساءل كيفية تحليل متداخلة والطبقات، أي بمعنى.

select name from users where name = "peter" and (age = 29 or age = 30)

والإنتاج الحالي من بلدي 'combinedPredicate "يبدو مثل هذا:

def combinedPredicate = predicate ~ ("and"|"or") ~ predicate ^^ {
  case l ~ "and" ~ r => And(l,r)
  case l ~ "or" ~ r => Or(l,r)
}

وحاولت الرجوع متكرر إنتاج combinedPredicate داخل نفسه ولكن هذا يؤدي إلى ستاكوفيرفلوو.

وراجع للشغل، أنا مجرد تجريب هنا ... عدم تنفيذ كامل ANSI-99 المواصفات.)

هل كانت مفيدة؟

المحلول

حسنا، العودية يجب أن تكون محددة بطريقة أو بأخرى. في هذه الحالة، يمكنك أن تفعل هذا:

def combinedPredicate = predicate ~ rep( ("and" | "or" ) ~ predicate )
def predicate = "(" ~ combinedPredicate ~ ")" | simplePredicate
def simplePredicate = ...

وهكذا لن كومة تجاوز ل، لعنة، لديه لأول مرة لقبول الحرف. وهذا هو الجزء المهم - إذا كنت دائما ضمان العودية لن يحدث دون قبول أول حرف، فلن تحصل إلى العودية لانهائية. ما لم يكن، بالطبع، لديك إدخال لانهائية. : -)

نصائح أخرى

ووتجاوز كومة كنت تعاني من هو على الأرجح نتيجة للغة الأيسر العودية:

def combinedPredicate = predicate ~ ...
def predicate = combinedPrediacate | ...

ووcombinators محلل في سكالا 2.7 هي الترميز التكراري النموذجي. الترميز التكراري النموذجي لديهم مشاكل مع هذه لأن لديهم أي فكرة عن كيفية رمز المحطة هو عندما تواجه لأول مرة. وأنواع أخرى من موزعي مثل سكالا 2.8 في combinators تهوى تجميع العناصر محلل ليس لديهم مشكلة مع هذا، على الرغم من أنك سوف تحتاج إلى تحديد قواعد استخدام lazy vals بدلا من الطرق، كما يلي:

lazy val combinedPredicate = predicate ~ ...
lazy val predicate = combinedPrediacate | ...

وبدلا من ذلك، هل يمكن أن ريفاكتور اللغة لتجنب العودية اليسرى. من المثال كنت إعطائي، الأمر الذي يتطلب الأقواس في هذه اللغة يمكن أن تحل المشكلة على نحو فعال.

def combinedPredicate = predicate ~ ...
def predicate = "(" ~> combinedPrediacate <~ ")" | ...

والآن كل مستوى أعمق من العودية يتوافق مع أقواس آخر تحليل. كنت أعلم أنك ليس لديك لعنة أعمق عند نفاد من الأقواس.

وبعد القراءة عن حلول لأسبقية المعامل وخرجت بما يلي:

  def clause:Parser[Clause] = (predicate|parens) * (
            "and" ^^^ { (a:Clause, b:Clause) => And(a,b) } |
            "or" ^^^ { (a:Clause, b:Clause) => Or(a,b) } )

  def parens:Parser[Clause] = "(" ~> clause  <~ ")"

ويتش هو على الارجح مجرد وسيلة أخرى كتابة ما كتبDaniel؛)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top