2

我是 Irony 编程的新手。我正在处理的第一个测试示例是计算数学形状(面积、体积......)

在简单模式下,它工作正常。但挑战是我想让它成为可选的。例如,如果我选择圆形作为形状,那么我只需要半径。另外,如果我选择矩形作为形状,我需要高度和宽度。所以,我想知道当形状是圆形时如何获得一个数字作为半径,以及当形状是矩形时如何获得 2 或 3 个数字。

            var program = new NonTerminal("program");
            var shapeType = new NonTerminal("shapeType");
            var shapeTypes = new NonTerminal("shapeTypes");
            var circle = new NonTerminal("circle");
            var square = new NonTerminal("square");
            var rectangle = new NonTerminal("rectangle");
            var triangle = new NonTerminal("triangle");
            var commandList = new NonTerminal("commandList");
            var command = new NonTerminal("command");
            var width = new NonTerminal("width");
            var height = new NonTerminal("height");
            var length = new NonTerminal("length");
            var radius = new NonTerminal("radius");
            var number = new NumberLiteral("number");
            var operation = new NonTerminal("operation");

            this.Root = program;

            program.Rule = shapeType + radius + commandList |
                shapeType + length + commandList |
                shapeType + width + commandList |
                shapeType + length + width + commandList |
                shapeType + height + commandList |
            shapeType + length + width + height + commandList;
            shapeType.Rule = Symbol("set") + "shape" + ":" + shapeTypes + ".";
            shapeTypes.Rule = Symbol("circle") | "square" | "rectangle" | "triangle";
            radius.Rule = Symbol("set") + "radius" + ":" + number + ".";
            height.Rule = Symbol("set") + "height" + ":" + number + ".";
            width.Rule = Symbol("set") + "width" + ":" + number + ".";
            length.Rule = Symbol("set") + "length" + ":" + number + ".";

            triangle.Rule = height + width | height + width + length;
            rectangle.Rule = height + width | height + width + length;
            square.Rule = height + width | height + width + length;
            circle.Rule = radius;
            operation.Rule = Symbol("area") | "volume";
            commandList.Rule = MakeStarRule(commandList, null, command);
            command.Rule = Symbol("what") + "is" + operation + ".";

它的行为是这样的:对于圆形示例,我希望我的代码只接收半径而不是更多(如下面的代码 - 清单 1)。但是,当语法像清单 2 时,它也可以工作。所以,我想要编译中的特定情况。

清单 1

set shape : circle.
set radius : 10.
what is area.

清单 2

set shape : circle.
set length : 10.
set width : 5.
what is area.

它们都得出相同的答案,我们知道清单 2 的参数是错误的。

4

2 回答 2

1

我了解您要做什么,但是,这种“条件”行为不是使用语法来完成的——这会使语法更难理解,而且维护起来也很麻烦,而且也不是那么容易。

相反,你将拥有你所拥有的。将输入字符串传递给 Irony 后,它会返回一个“解析树”:如何使用 Irony 在 C# 中为表达式生成和显示 ParseTree?

解析树还可以进一步转换为 AST(抽象语法树),Irony 也有这方面的示例。

一旦你有了解析树/AST,你将不得不对令牌进行简单的分析,并标记所有不适当的行为。

通过分析,我的意思是,遍历标记,保留某种“上下文信息”。

本质上,逻辑将如下所示:

if set shape was set to circle:
  if set length exists
     return true; // nothing wrong here, we can calculate area.
  if set length exists and set width exists
     return true;

  return false; // error: we can't decide it..

希望能帮助到你。Irony 还提供了一些简单的示例,如何使用解释器构建实际的编程语言。

于 2014-12-26T21:11:21.307 回答
0

要使规则可选,请使用其Q()上的方法

于 2014-12-01T11:45:38.513 回答