简体   繁体   English

PEGjs 中的条件语法规则

[英]Conditional grammar rule in PEGjs

I'm trying to implement a simple DSL that parses basic arithmetic expressions.我正在尝试实现一个解析基本算术表达式的简单 DSL。 This needs to be done in the browser, so I'm using PEGjs to generate the parser.这需要在浏览器中完成,所以我使用 PEGjs 来生成解析器。

Terms in the expression can be numbers (integers or real), variables (variables are properties on a context object passed to the parser), conditionals or properties accessed via dot notation.表达式中的术语可以是数字(整数或实数)、变量(变量是传递给解析器的上下文对象上的属性)、条件或通过点表示法访问的属性。

I want the conditionals to look like this condition?value , where if condition is true, the term equates to value .我希望条件看起来像这个condition?value ,如果condition为真,则该术语等于value The variables on either side of the ? ?两侧的变量? could also be dot notation accessed properties of an object like this object.property1?object.property2 .也可以是像这样object.property1?object.property2这样的对象的点符号访问属性。

So if the parser is passed an object like this:因此,如果解析器传递了一个像这样的对象:

context = {
  depth: 100,
  material: {
    thickness: 20
    include: true
  }
  edge: {
    face: 4.5
  }
}

The expression:表达方式:

500 + depth + material.include?edge.face + material.thickness should equate to 624.5 . 500 + depth + material.include?edge.face + material.thickness应该等于624.5

I've been using the PEGjs online editor.我一直在使用 PEGjs 在线编辑器。 I've tried lots of different approaches, but I can't seem to nail the conditional.我尝试了很多不同的方法,但我似乎无法确定条件。 Everything else works.其他一切都有效。 Here are the relevant rules:以下是相关规则:

Variable "variable"
  = variable:identifier accessor:("." identifier)* {
      var result = context[variable], i

      for (i = 0; i < accessor.length; i++) {
        result = result[accessor[i][1]]
      }

      return result
    }

identifier
  = identifier:$([0-9a-zA-Z_\$]+)

Conditional
  = condition:Variable "?" value:Variable {
    return condition ? value : 0
  }

I've looked at the example grammar for javascript in the PEGjs github repo, and the conditional rule looks a lot like what I've got here, but I still can't get it to work.我在 PEGjs github repo 中查看了 javascript 的示例语法,条件规则看起来很像我在这里得到的,但我仍然无法让它工作。

What would be the correct way to implement a conditional statement like the one I've described in a PEGjs rule?实现像我在 PEGjs 规则中描述的那样的条件语句的正确方法是什么?

I know that this is a bit late, but the issue is that your variable is a string evaluating to "material.include" .我知道这有点晚了,但问题是您的variable是一个评估为"material.include"的字符串。

Look at this code:看看这段代码:

var result = context[variable], i

You are trying to access a property named "material.include" from your context object, which would look like this:您正在尝试从上下文对象访问名为“material.include”的属性,它如下所示:

{
    "material.include": true
}

Rather than trying to access the object referenced by the "material" property, and then the "include" property off the resulting object, which would look like this:而不是尝试访问“material”属性引用的对象,然后访问结果对象的“include”属性,它看起来像这样:

{
    "material": {
        "include": true
    }
}

The solution would be to split the variable string by "."解决方案是用"."分割变量字符串"." characters and then recursively find your property:字符,然后递归地找到你的财产:

Variable "variable"
  = variable:identifier accessor:("." identifier)* {
      var path = variable.split(".");
      var result = path.reduce( (nextObject, propName) => nextObject[propName], context );

      for (var i = 0; i < accessor.length; i++) {
        result = result[accessor[i][1]]
      }

      return result
    }

Note that this solution is not complete, as it will cause an error if you try to access material.include where material is never defined in your context.请注意,此解决方案并不完整,因为如果您尝试访问material.include ,其中material从未在您的上下文中定义,则会导致错误。 You may want to add additional error handling, but it does work for the given example.您可能想要添加额外的错误处理,但它确实适用于给定的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM