使用“术语解析器”解析漩涡花饰的内容

时间:2017-03-04 07:37:29

标签: isabelle

我想在Isabelle的cartouches中实现一个特定于域的语言(带有自己的解析器)。例如,我希望术语(MY ‹123›, 3)为子串123调用我自己的解析器,但通常将其余的解析为术语。

关注HOL/ex/Cartouche_Examples.thy,我了解如何为MY ‹...›形式的子项安装我自己的解析翻译,以及如何将广告素材的内容设为string*Position.T或{{ 1}}。

我也理解如何使用Isabelle的解析器组合器来编写Symbol_Pos.T list类型的解析器。

但我无法找到如何将解析器应用于字符串(或term parser)。

换句话说,我仍然缺少的是一个功能

Symbol_Pos.T list

fun parse_cartouche ctx (cartouche:string) (pos:Position.T) : term = ??? 类型的解析器应用于字符串term parser(并正确地将解析错误报告给顶层)。

澄清:

  • 我想利用Isabelle的现有基础架构来跟踪/报告解析位置。例如,如果存在解析错误,我希望Isabelle / jEdit中的代码为红色,如果在我自己的语言中,我会调用像Args.parse_term这样的解析器,我希望Isabelle / jEdit颜色变量正确,并通过控制悬停获取类型信息。

  • 我不想重新实现我自己的解析器来处理像int这样的常见事情,但是如果我至少得到前面的要点那么可以这样做。 (但是,将我的语言的子字符串解析为术语,我将不得不使用一些现有的解析函数,因为我不能自己重新实现Isabelle语法。

以下是我目前的完整代码(带有cartouche的虚拟实现。)

parse_cartouche

2 个答案:

答案 0 :(得分:1)

因为这是一个相对罕见的用例,我不确定"规范"解决方案已经出现了。但我至少可以从我自己的代码中给出两个例子来帮助说明一般方法。

用术语

评估ML代码

source

在给定函数eval_term : string -> term的情况下,以下解析翻译从一个cartouche中提取一些ML源,将其评估为term,然后将其用作解析翻译的结果。

fun term_translation ctxt args =
  let
    fun err () = raise TERM ("Splice.term_translation", args)
    fun input s pos =
      let
        val content = Symbol_Pos.cartouche_content (Symbol_Pos.explode (s, pos))
        val (text, range) = Symbol_Pos.implode_range (Symbol_Pos.range content) content
      in
        Input.source true text range
      end
  in
    case args of
      [(c as Const (@{syntax_const "_constrain"}, _)) $ Free (s, _) $ p] =>
        (case Term_Position.decode_position p of
          SOME (pos, _) => c $ eval_term (input s pos) ctxt $ p
        | NONE => err ())
    | _ => err ()
end

嵌入XML

source

这个允许我将XML文字嵌入到术语中,然后将其解释为术语。

syntax "_cartouche_xml" :: "cartouche_position \<Rightarrow> 'a"  ("XML _")

parse_translation\<open>
let
  fun translation args =
    let
      fun err () = raise TERM ("Common._cartouche_xml", args)
      fun input s pos = Symbol_Pos.implode (Symbol_Pos.cartouche_content (Symbol_Pos.explode (s, pos)))
      val eval = Codec.the_decode Codec.term o XML.parse
    in
      case args of
        [(c as Const (@{syntax_const "_constrain"}, _)) $ Free (s, _) $ p] =>
          (case Term_Position.decode_position p of
            SOME (pos, _) => c $ eval (input s pos) $ p
          | NONE => err ())
      | _ => err ()
  end
in
  [(@{syntax_const "_cartouche_xml"}, K translation)]
end
\<close>

更新

以下代码应该允许您将Input.source转换为解析器组合器可消化的内容,包括完整的位置信息:

ML ‹
  val input = ‹term"3 + 4"›;
  (* a bit more complicated than just Input.pos_of because otherwise the position includes the
     outer cartouche brackets, which manifests as an off-by-one-error in the markup *)
  val pos = Input.source_explode input |> Symbol_Pos.range |> Position.range_position;
  val str = Input.source_content input;
  val toks = Token.explode Keyword.empty_keywords pos str;
  val parser = Args.$$$ "term" |-- Args.embedded_inner_syntax;
  parser toks |> fst |> Syntax.read_term @{context}
›

答案 1 :(得分:1)

基于@ larsrh&#39; answer和自己的实验,我想出了以下答案。

  • 解析翻译将cartouche内容作为字符串与位置一起获取。可以使用Symbol_Pos.T list转换为Symbol_Pos.cartouche_content o Symbol_Pos.explode。 (这在Cartouche_Examples.thy的例子中有所涉及,由Isabelle提供。)
  • Symbol_Pos.T list可以使用Source.source转换为包含Symbol_Pos.T的{​​{1}}。
  • 包含Source.of_list的{​​{1}}可以使用Source.source转换为包含Symbol_Pos.T的{​​{1}}。
  • 我们使用Source.source从此来源删除空白徽标。
  • 并使用Token.T将结果转换为Token.source'
  • 最后,Token.source_proper类型的解析器可以应用于此类Token.T list。 (或者,如果我们有Source.exhaust,那么我们还需要提供一个上下文。)

需要完成一些额外的工作:向'a parser添加EOF以允许解析器检测输入的结束。处理解析器中的错误(以获得很好的错误消息)。

下面的代码是一个完整的评论工作示例(对于Isabelle 2016-1),也可以找到来源here

Token.T list