【问题标题】:SML: Count nodes with Elements in a GrammarSML:使用语法中的元素计算节点
【发布时间】:2018-02-21 22:35:12
【问题描述】:

我在 SML 中创建了以下简单语法:

datatype identifier = IdentE of char;

datatype term = ID of identifier | MultE of term * term * identifier;

datatype expression = Term of term | AddE of expression * expression * term;

我想计算存在的 IdentE 数据类型的数量。

我对如何做到这一点的猜测如下,当然这不起作用,但我不确定如何实际完成这项任务:

fun sum(Empty)= 0 | sum(Term) = sum(ID) + | sum(IdentE) = 1|| sum(AddE(AddE, Term) =  sum(AddE) + sum(Term) |  sum(MultE(MultE, IdentE) =  sum(MultE) + sum(IdentE);

我对 SML 很陌生,所以我可能犯了一个菜鸟错误。

【问题讨论】:

    标签: nodes grammar sml


    【解决方案1】:

    您的数据类型似乎对数学表达式的某些子集进行了建模,并且您已将加法、乘法和变量拆分为两个单独的数据类型 expression 和 term。因为terms只指terms而不回表达式s,所以表达式a + (b × c) em> 可以编码为:

    AddE (Term (ID (IdentE #"a")),
          Term (MultE (ID (IdentE #"b")),
                       ID (IdentE #"c")),
          IdentE #"?")
    

    但你不能编码表达式a × (b + c)。

    我不确定为什么加法有三个参数,大概是二元运算符。

    这是您的 sum 函数,具有适当的间距和换行符:

    fun sum(Empty) = 0
      | sum(Term) = sum(ID) +
      | sum(IdentE) = 1
     || sum(AddE(AddE, Term) = sum(AddE) + sum(Term)
      | sum(MultE(MultE, IdentE) = sum(MultE) + sum(IdentE)
    

    一些事情变得明显:

    • 您在发布代码之前没有仔细阅读自己的代码。
    • 您的数据类型中没有Empty 构造函数。什么是“空表达式”?
    • 您似乎忘记完成第二行中+之后的表达式。
    • 您在第四行的| 太多,而在第四行和第五行的) 太少。
    • 您的函数sum 不能同时处理多种类型的值。如果它在一行中接受与 AddE (...) 匹配的值,则它也不能在另一行中接受与 MultE (...) 匹配的值,因为它们属于不同的类型。
    • 您要进行模式匹配的每个值构造函数都没有其参数。每个递归调用都是针对值构造函数的名称而不是传入的值的参数进行的。如果您想要一个接受 表达式s 的函数,可以如下所示:

      fun sum (AddE (e1, e2, t)) = sum e1 + sum e2 + ...
        | sum (Term t) = ...
      
    • 由于您有多种递归数据类型,最好的办法是拥有多个函数来处理每种数据类型的递归。 (这不是绝对必要的,但是您也有一些非常复杂的模式。)

      fun sum (AddE (e1, e2, t)) = sum e1 + sum e2 + sumTerm t
        | sum (Term t) = sumTerm t
      
      and sumTerm (ID id) = 1
        | sumTerm (MultE (t1, t2, id)) = sumTerm t1 + sumTerm t2 + 1
      

      同样,我不知道为什么加法有第三项,为什么乘法有第三个标识符,以及为什么你有多个数据类型开始。

    如果我要为一个简单的算术语法树建模并计算它的变量数量,我会从 one 数据类型开始,二元运算符只有 two 每个参数:

    datatype expr = AddE of expr * expr
                  | MultE of expr * expr
                  | ConstE of int
                  | VarE of string
    

    有了这个数据类型定义,

    • a + (b × c) 变为 AddE (VarE "a", MultE (VarE "b", VarE "c")),并且
    • a × (b + c) 变为 MultE (VarE "a", AddE (VarE "b", VarE "c"))。

    我可以创建一个函数来计算表达式中变量的数量,如下所示:

    fun countVars (AddE (e1, e2)) = countVars e1 + countVars e2
      | countVars (MultE (e1, e2)) = countVars e1 + countVars e2
      | countVars (ConstE const) = 0
      | countVars (VarE varname) = 1
    

    我可能有兴趣获取这些变量的列表:

    fun getVars (AddE (e1, e2)) = getVars e1 @ getVars e2
      | getVars (MultE (e1, e2)) = getVars e1 @ getVars e2
      | getVars (ConstE const) = []
      | getVars (VarE varname) = [varname]
    

    【讨论】:

    • 对于混乱的代码我很抱歉,我刚刚复制了我记下的可能的解决方案,但是在尝试一个简单的表单时它不起作用。你是对的,我不打算使用三个参数。由于这是我第一次使用 SML 或为此进行函数式编程,因此这条消息确实消除了我对语言语法的一些困惑,并且提供了非常丰富的信息。
    • @AndrewObrigewitsch:首先是平衡括号。 :-)
    猜你喜欢
    • 2021-01-04
    • 1970-01-01
    • 2015-09-28
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多