美文网首页
创建自定义块 - 运算符优先级

创建自定义块 - 运算符优先级

作者: mimimomo | 来源:发表于2018-02-07 10:05 被阅读61次

title: 创建自定义块 - 运算符优先级

代码生成器用于将Blockly的程序转换为JavaScript,Python,PHP,Lua,Dart等。为新块创建代码生成器时最具挑战性的问题是处理操作的顺序,以便生成的代码按预期执行。

坑爹的括号


考虑以下块的装配。

如果生成器不知道运算符优先级,则生成的JavaScript代码将是:

alert(2 * 3 + 4);

这显然是不正确的,因为乘法运算符分割加法,先乘以3。一个解决方案是将每个值块的结果包裹在括号中:

alert(((2) * ((3) + (4)));

这个解决方案完美地工作,但它导致非常凌乱的代码与大量的冗余括号。对于一些使用情况,这不是一个问题。如果人眼永远不会看到生成的代码,那么这是可以接受的。但是,Blockly经常被用作介绍编程的教育工具,一种依赖于生成人类可读代码的用例。

Good Parentheses


为了生成没有不合理数量的括号的正确代码,每个语言生成器都提供了有序的优先级列表。这里是JavaScript的列表:

Blockly.JavaScript.ORDER_ATOMIC = 0;         // 0 "" ...
Blockly.JavaScript.ORDER_MEMBER = 1;         // . []
Blockly.JavaScript.ORDER_NEW = 1;            // new
Blockly.JavaScript.ORDER_FUNCTION_CALL = 2;  // ()
Blockly.JavaScript.ORDER_INCREMENT = 3;      // ++
Blockly.JavaScript.ORDER_DECREMENT = 3;      // --
Blockly.JavaScript.ORDER_LOGICAL_NOT = 4;    // !
Blockly.JavaScript.ORDER_BITWISE_NOT = 4;    // ~
Blockly.JavaScript.ORDER_UNARY_PLUS = 4;     // +
Blockly.JavaScript.ORDER_UNARY_NEGATION = 4; // -
Blockly.JavaScript.ORDER_TYPEOF = 4;         // typeof
Blockly.JavaScript.ORDER_VOID = 4;           // void
Blockly.JavaScript.ORDER_DELETE = 4;         // delete
Blockly.JavaScript.ORDER_MULTIPLICATION = 5; // \*
Blockly.JavaScript.ORDER_DIVISION = 5;       // /
Blockly.JavaScript.ORDER_MODULUS = 5;        // %
Blockly.JavaScript.ORDER_ADDITION = 6;       // +
Blockly.JavaScript.ORDER_SUBTRACTION = 6;    // -
Blockly.JavaScript.ORDER_BITWISE_SHIFT = 7;  // << >> >>>
Blockly.JavaScript.ORDER_RELATIONAL = 8;     // < <= > >=
Blockly.JavaScript.ORDER_IN = 8;             // in
Blockly.JavaScript.ORDER_INSTANCEOF = 8;     // instanceof
Blockly.JavaScript.ORDER_EQUALITY = 9;       // == != === !==
Blockly.JavaScript.ORDER_BITWISE_AND = 10;   // &
Blockly.JavaScript.ORDER_BITWISE_XOR = 11;   // ^
Blockly.JavaScript.ORDER_BITWISE_OR = 12;    // |
Blockly.JavaScript.ORDER_LOGICAL_AND = 13;   // &&
Blockly.JavaScript.ORDER_LOGICAL_OR = 14;    // ||
Blockly.JavaScript.ORDER_CONDITIONAL = 15;   // ?:
Blockly.JavaScript.ORDER_ASSIGNMENT = 16;    // = += -= \*= /= %= <<= >>= ...
Blockly.JavaScript.ORDER_COMMA = 17;         // ,
Blockly.JavaScript.ORDER_NONE = 99;          // (...)

此列表的大部分直接取自JavaScript的语言规范language spec,其中ORDER_ATOMIC添加到开始,ORDER_NONE添加到结尾。

应用这些规则会在每个块的生成器中的两个地方使用到。第一个地方是从连接的值块获取生成的代码。在这种情况下,我们传递常数,该常数表示与子块生成的代码相邻的任何运算符的最大绑定强度。例如:

var arg0 = Blockly.JavaScript.valueToCode(this, 'NUM1', Blockly.JavaScript.ORDER_DIVISION);

第二个是从值块返回生成的代码。在这种情况下,我们传递常量,它代表块生成代码中任何运算符的最小绑定强度。例如:

return [arg0 + ' / ' + arg1, Blockly.JavaScript.ORDER_DIVISION];

如果子块返回的顺序值弱于或等于父块的顺序参数的顺序值,那么valueToCode函数将自动将子块代码的内容括在括号中,以防止它由父块的代码割裂开。

下面是一些更多的例子。在每种情况下,块具有被表示为“X”的一个连接子块('X'的内容是未知的并且无关紧要)。第二列列出可能分裂“X”的最强运算符。第三列列出了块的最终代码中最弱的运算符。

生成的代码 Max strength against X Min strength of block
X + 1 ORDER_ADDITION ORDER_ADDITION
Math.sqrt(X) ORDER_NONE ORDER_MEMBER
!X && false ORDER_LOGICAL_NOT ORDER_LOGICAL_AND
foo[X % 60] ORDER_MODULUS ORDER_MEMBER

数学很难


还是不明白?没问题。只需使用ORDER_ATOMIC作为每次调用valueToCode的顺序,并使用ORDER_NONE作为每个值块上最终返回语句的顺序。结果代码将被不必要的括号侵蚀,但是保证是正确的。

相关文章

  • 创建自定义块 - 运算符优先级

    title: 创建自定义块 - 运算符优先级 代码生成器用于将Blockly的程序转换为JavaScript,P...

  • HTML 日常了解10(js篇)

    Unicode编码 相等运算符 条件运算符 运算符的优先级 代码块

  • 2018-12-01

    赋值运算符 关系运算符 Unicode编码 相等运算符 条件运算符 运算符的优先级 代码块 js操作属性 js换肤...

  • 一些常用的单行语句

    运算符优先级 &&优先级高于|| 三元运算符会先运算被其他三元运算符包裹的内容,因此以下两行等价 快速创建数字数组...

  • 运算符及js操作属性

    关系运算符 相等运算符 条件运算符 运算符的优先级 代码块 js操作属性 js操作style属性 js操作clas...

  • JS操作属性、函数

    条件运算符 运算符的优先级 代码块 JS操作属性 JS换肤 JS操作style属性 JS操作

  • JS笔记8:运算符及优先级

    1. 运算符 2. 运算符优先级 优先级运算符优先级 口诀括号一, //括号运算符[] ()单目二;...

  • 运算符的优先级、代码块

    运算符的优先级: , 运算符 使用,可以分割多个语句,一般可以在声明多个变量时使用 代码块: JS中的代码块,...

  • Kotlin(运算符重载)

    运算符重载 Kotlin 允许我们实现一些我们自定义类型的运算符实现。这些运算符有固定的表示,和固定的优先级。为实...

  • python条件控制语句

    运算符优先级 运算符优先级 运算符优先级从上往下逐渐变低**指数 (最高优先级)~ + -按位翻转, 一元加号和减...

网友评论

      本文标题:创建自定义块 - 运算符优先级

      本文链接:https://www.haomeiwen.com/subject/idkqmttx.html