2

我需要解析一种不是我设计的简单专有语言,所以我无法更改语言。我需要 C# 中的结果,所以我一直在使用 TinyPG,因为它非常易于使用,并且不需要外部库来运行解析器。TinyPG 生成一个简单的 LL(1) 解析器。

我目前遇到的问题与语言如何将文件划分为部分有关。它有用于不同类型变量的部分,设置它们的初始值,方程定义等。我只关心声明变量的部分,所以我想忽略其余部分。我不知道其他部分的所有规则,也不想弄清楚它们。它们可能被视为评论。

这是一个代码示例:

  PARAMETER
    Density             AS REAL
    CrossSectionalArea  AS REAL

 SET # Parameter values
    T101.FO                 := "SimpleEventFOI::dummy";
    T101.CrossSectionalArea := 1    ; # m2

EQUATION
    OutSingleInt = SingleInt;
    OutArrayInt = ArrayInt;

我关心 PARAMETER 和 SET 部分,但不关心 EQUATION 部分。如您所见,问题在于这些部分没有 END 标记。所以我不知道如何告诉语法当你得到一个不同的关键字时一个节结束,但是新的关键字可能会开始一个新的节。在我的尝试中,新部分开始关键字被消耗以关闭旧部分。

还有比我在这里列出的更多的部分,其中一些我关心,一些我不关心。它们似乎分为两种类型,“看起来像参数”,在语句末尾没有分号,“看起来像方程”。这种语言不区分大小写或空格。这些部分可以按任何顺序排列。(例如,SET、EQUATION、PARAMETER) 除了注释之外,整件事都可以写在一行上。

目前我正在通过使用正则表达式来找到我感兴趣的部分来解决这个问题,并且只将这些部分提供给解析器,但是我也很难想出一个适用于所有情况的正则表达式,但是不会意外地在评论中选择关键字。我可能最终只是扩展了这个解决方法来解决它的问题,但直接在语法中解决问题会更好。这可能不是 LL(1) 语言。

4

1 回答 1

0

我尝试了以下 tpg 代码,它可以解析您的示例。看起来 TinyPG 无法区分关键字和 ID,所以我稍微破解了 ID。

//Tiny Parser Generator v1.3
//Copyright © Herre Kuijpers 2008-2012

<% @TinyPG Namespace="Test" %>

PARAMETER   -> @"PARAMETER";
SET         -> @"SET";
EQUATION    -> @"EQUATION";

AS          -> @"AS";

ID          -> @"\b(?!(PARAMETER|SET|EQUATION)\b)([a-zA-Z]\w+)";
DOT         -> @"\.";
EQ          -> @":=";
EXPR        -> @"\d|""[^""]*""";
END         -> @";";

[Skip] WS   -> @"\s+|#[^\r\n]+";

EQDECL      -> @"\b(?!(PARAMETER|SET|EQUATION)\b)([^#;]+)";
Equations   -> EQUATION (EQDECL END)*;

Parameters  -> PARAMETER ParamDecl*;
ParamDecl   -> ID AS ID;

Sets        -> SET SetDecl*;
SetDecl     -> FullId EQ EXPR END;
FullId      -> ID DOT ID;

Section     -> Equations | Parameters | Sets;

Start       -> Section*;
于 2015-06-04T09:15:28.260 回答