парсинг рекурсивных структур в scala

Это - мой подход:

dim arrFormaA(15)
arrFormaA( 0 ) = "formaA_01.txt"
arrFormaA( 1 ) = "formaA_02.txt"
arrFormaA( 2 ) = "formaA_03.txt"
arrFormaA( 3 ) = "formaA_04.txt"
arrFormaA( 4 ) = "formaA_05.txt"
arrFormaA( 5 ) = "formaA_06.txt"
arrFormaA( 6 ) = "formaA_07.txt"
arrFormaA( 7 ) = "formaA_08.txt"
arrFormaA( 8 ) = "formaA_09.txt"
arrFormaA( 9 ) = "formaA_10.txt"
arrFormaA( 10 ) = "formaA_11.txt"
arrFormaA( 11 ) = "formaA_12.txt"
arrFormaA( 12 ) = "formaA_13.txt"
arrFormaA( 13 ) = "formaA_14.txt"
arrFormaA( 14 ) = "formaA_15.txt"

Wscript.echo(UBound(arrFormaA))
''displays "15"

For i = 0 To UBound(arrFormaA)-1
    Wscript.echo(arrFormaA(i))
Next

Hope это помогает.

7
задан p3t0r 26 November 2009 в 08:49
поделиться

3 ответа

Ну, рекурсию нужно как-то разграничивать. В этом случае вы можете сделать это:

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

Таким образом, стек никогда не будет переполнен, потому что для рекурсии он сначала должен принять символ. Это важная часть - если вы всегда гарантируете, что рекурсия не произойдет без предварительного принятия символа, вы никогда не попадете в бесконечную рекурсию. Если, конечно, у вас нет бесконечного ввода. : -)

11
ответ дан 6 December 2019 в 10:51
поделиться

Переполнение стека, которое вы испытываете, вероятно, является результатом леворекурсивного языка:

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

Комбинаторы синтаксического анализатора в Scala 2.7 являются синтаксическими анализаторами рекурсивного спуска. У парсеров с рекурсивным спуском есть проблемы с этим, потому что они понятия не имеют, каков терминальный символ, когда они впервые сталкиваются с ним. Другие виды синтаксических анализаторов, такие как комбинаторы синтаксического анализатора Packrat в Scala 2.8, не будут иметь с этим проблем, хотя вам нужно будет определить грамматику, используя lazy val s вместо методов, например:

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

В качестве альтернативы, вы можете провести рефакторинг языка, чтобы избежать левой рекурсии. Из примера, который вы мне приводите, требование круглых скобок в этом языке могло бы эффективно решить проблему.

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

Теперь каждый более глубокий уровень рекурсии соответствует другим анализируемым скобкам. Вы знаете, что не делаете

7
ответ дан 6 December 2019 в 10:51
поделиться

Прочитав о решениях для приоритета операторов, я пришел к следующему:

  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;)

0
ответ дан 6 December 2019 в 10:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: