【问题标题】:Writing a parser in JavaScript for matrix arithmetic用 JavaScript 编写解析器以进行矩阵运算
【发布时间】:2020-03-08 14:07:17
【问题描述】:

我目前正在编写一个解决矩阵方程的程序,目前,我正在努力让解析器工作。但是,我不知道从哪里开始。

我有一个字符串数组,用于跟踪矩阵和运算符。例如方程

[[0, 0],[4, 5]] + [[4, 8], [12, 6]]

将按如下方式存储:

variables = ["$", "+", "$"]
matrices = [[[0, 0],[4, 5]], [[4, 8], [12, 6]]

因此,每个“$”符号代表不同数组中的一个矩阵。我还希望能够用不同的表达式包装我的矩阵,例如:

det([[0, 0],[4, 5]]) + inv([[0, 0],[4, 5]] + [[4, 8], [12, 6]])

其中det和inv分别对应行列式和逆行式。

在我的代码中,将存储为:

variables = ["d", "e", "t", "(", "$", ")", "+", "i", "n", "v", "(", "$", "+", "$", ")"]
matrices = [ [[0, 0],[4, 5]], [[0, 0],[4, 5]],  [[4, 8], [12, 6]] ]

我的直觉是使用上下文无关语法来构建解析树,因为正则表达式在括号中不起作用......(?)。我也在考虑将我的表达式简单地转换为后缀符号,看看是否可行。

【问题讨论】:

    标签: javascript parsing


    【解决方案1】:

    使用上下文无关语法构建解析树是我认为的最佳整体方法。 (如果您不熟悉上下文无关语法并且手边没有相关的教科书,您可以尝试阅读有关该主题的Wikipedia article。)

    如果您环顾四周,您会发现很多关于如何为算术表达式编写上下文无关文法的示例。 (上面的 Wikipedia 链接包含一个算术语法示例。)确实,其中大多数是用于简单的计算器,而不是用于矩阵算术。 但这没关系。

    编写解析器的重要见解是语法就是语法。因此,无论被计算的原始对象是整数、浮点数还是复数,或者在您的情况下是数组,计算器的语法形式都将是相同的。唯一的区别在于文字对象的语法。您可以进一步了解这个事实:运算符本身的编写方式不会改变语法的基本结构,因此您可以将相同的样式用于计算器,例如使用 计算布尔表达式, ornot 运算符。

    对于简单的数字计算器,文字对象(即数字)通常只是从词法分析器中弹出,因为它们没有内部结构。但显然矩阵确实具有内部结构,基于正则表达式的词法分析器并不适合解析结构化文本。更好的解决方案是将矩阵文字视为一系列标记(至少,数字和符号[],),并包括在您可以使用的无上下文语法产品中解析矩阵。

    实际上,矩阵是一个逗号分隔的向量列表,每个向量都是一个逗号分隔的数字列表。这与任何其他逗号分隔列表,甚至任何分隔列表语法相同,无论分隔符的精确拼写如何。 (在解析包含函数调用的表达式的语法中,您需要相同类型的产生式来解析函数的参数列表。)

    分隔列表的上下文无关语法的基本形式如下,您可以将 X 替换为列表中元素的类型:

    /* Only parses lists with at least one element */
    list_of_X: X
             | list_of_X ',' X
    

    如果允许空列表(矩阵可能不是这种情况,但在函数调用中很常见),您可以将上述与另一种模式结合起来:

    optional_list_of_X: %empty
                      | list_of_X
    

    您的语法将包括如下产生式:

    expression: matrix
              | /* ... all the other forms of an expression */
    
    matrix: '[' list_of_vector ']'
    vector: '[' list_of_number ']'
    

    这里我使用了bison 语法,因为它是编写上下文无关语法的常用方法,但每个解析器生成器都有自己的特点。

    【讨论】:

      猜你喜欢
      • 2015-08-01
      • 2011-08-25
      • 1970-01-01
      • 2015-06-25
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 2018-09-01
      • 1970-01-01
      相关资源
      最近更新 更多