代码之家  ›  专栏  ›  技术社区  ›  Mateja Petrovic

使用Javascript标记的模板文本编写解释器

  •  3
  • Mateja Petrovic  · 技术社区  · 8 年前

    你有没有想过,如果你能在普通的老Javascript中使用其他语言中你最喜欢的特性会很酷。例如,我希望能够使用F#pipeline operator'|>',但是JS中的pipeline operator的建议只是第1阶段ATM。

    首先,我尝试启用修复后符号,即“12+”=3。我想,使用ES6标记的模板文字我可能会有所收获,但我几乎没有触及表面。这只是概念的证明。

    const Interpret = (strings, ...expressions) => {
      
      const hasPlus = strings.map(s => s.trim()).join('').match(/[+]$/)
      
      return hasPlus ? expressions.reduce((t, c) => t + c, 0) : null
      
    }
    
    const a = 1
    const b = 2
    const c = 3
    const d = 4
    
    const result = Interpret`${a} ${b} ${c} ${d} +`
    
    console.log(result) // 10

    如果您能够访问字符串和表达式的数组,并保留它们的原始顺序(它们出现在两个反勾之间的顺序),那将是非常棒的。

    因为这将使我能够像这样计算数组的元素:我得到一个表达式了吗,太好了,把它推到堆栈上(只是一个数组作为开始)。。。接下来我得到一个表达式,酷,把它也推到堆栈上。。。接下来我得到一个表达式,不-它是加号运算符。现在我可以取前两个表达式求值的值“a”和值“b”,并将它们馈送给加号运算符(很可能是一个函数)。然后将返回值推送到堆栈上,依此类推。

    有没有人知道下一步该怎么走,或者可能转向另一个方向?

    这似乎是向前迈进了一步,谢谢mpm。

    const Interpret = (strings, ...expressions) => {
      
      const raw = strings
      .map( (s, i) => s + (expressions[i] || '') )
      .map(s => s.trim())
      
      const plusPosition = raw.findIndex(s => s.match(/[+]/))
      
      return raw.slice(0, plusPosition).reduce((t, c) => t + parseInt(c), 0)
        
    }
    
    const a = 1
    const b = 2
    const c = 3
    const d = 4
    
    const result = Interpret`${a} ${b} ${c} ${d} +`
    
    console.log(result)
    1 回复  |  直到 8 年前
        1
  •  1
  •   mpm    8 年前

    我确信顺序不会丢失,否则字符串模板将无用,字符串应该返回所有字符串部分,表达式rest参数具有所有表达式值。只需通过将每个表达式放在两个strings元素之间来重建顺序

    const i = (strings, ...expressions) => {
      const list = [];
      for (let i = 0; i < strings.length; i++) {
        if (strings[i].trim() !== '') {
          list.push(strings[i].trim())
        }
        if (i < expressions.length) {
          list.push(expressions[i])
        }
      }
      let stack = [];
      let result = 0;
      do {
        const token = list.shift()
        if (token === '+') {
          result = stack.reduce(function(result, value) {
            return result + value
          }, result)
          stack.length = 0;
    
        } else if (token === '-') {
          result = stack.reduce(function(result, value) {
            return result - value
          }, result)
          stack.length = 0;
        } else {
          stack.push(token)
        }
      } while (list.length > 0);
      return result;
    }
    const a = 2,
      b = 1,
      c = 4,
      d = 3,
      e = 4;
    console.log("result", i `${a} ${b} ${c} ${d} + ${e} - `);