有没有办法将上下文信息传递给解析器?

jbx*_*jbx 8 scala parser-combinators

我正在解析一个小的声明性语言,在一个范围内你可以声明变量(带有一个类型),然后再使用,就像在大多数其他语言中一样,使用名称(没有类型).

变量的声明如下所示:

?varname
?varname1 ?varname2 - type1
?varname3 ?varname4 ?varname5 - type2
Run Code Online (Sandbox Code Playgroud)

如果省略类型,则默认类型应该object与第一种情况类似.所以为此,我有一个特定的解析器,它返回一个我自己的域对象列表LiftedTerm(你可以假设它是一个带有变量名称和变量类型的元组,实际上它里面还有一些东西,但不相关对于这个问题):

def typed_list_variables : Parser[List[LiftedTerm]]= typed_variables.+ ^^ { case list => list.flatten.map(variable =>
        LiftedTerm(variable._1, variable._2 match {
          case "object" => ObjectType
          case _ => TermType(variable._2)
        })) }

def typed_variables = ((variable+) ~ (("-" ~> primitive_type)?)) ^^ {
    case variables ~ primitive_type => 
         for (variable <- variables) yield variable -> primitive_type.getOrElse("object")
}

def variable = """\?[a-zA-Z][a-zA-Z0-9_-]*""".r
def primitive_type = """[a-zA-Z][a-zA-Z0-9_-]*""".r
Run Code Online (Sandbox Code Playgroud)

这一切都很好.

现在,在相同的"范围"中,我必须解析存在对这些变量的引用的部分.该变量显然不会再次完整声明.因此,在上面的示例中,?varname1使用的位置将不包括type1.但是,当我解析其余的输入时,我希望得到正确LiftedTerm对象的引用,而不仅仅是一个字符串.

我有一些递归结构,所以我不希望在顶级解析器上进行这种映射.我不希望在我的RegexParsers对象中对这些进行"全局映射",因为大多数这些都是作用域的,并且仅与一小部分输入相关.

有没有办法将上下文信息传递给解析器?理想情况下,我将LiftedTerm(或者更好的是变量名称中的映射String -> LiftedTerm)列表传递给递归解析器调用.

(抱歉,如果这是显而易见的事情,我仍然是Scala的新手,甚至是解析器组合器的新手).

cho*_*ger 1

AFAIK,scala 的组合器解析器库仅限于上下文无关语法。因此,您的用例不受支持。

正确的方法是扩展scala.util.parsing.combinator.Parsers并提供一个Parser带有您的上下文的自定义类。您需要定义所有组合器来处理上下文。

编辑:正如下面指出的,解析器有一个方法intoflatMap因此,当您有一个可以生成上下文的解析器时,您可以将其与另一个需要单子样式上下文的解析器结合起来。