gpt4 book ai didi

c# - 如何创建解析器(lex/yacc)?

转载 作者:行者123 更新时间:2023-11-30 14:40:26 24 4
gpt4 key购买 nike

我有以下文件需要解析

--TestFile
Start ASDF123
Name "John"
Address "#6,US"
end ASDF123

-- 开头的行将被视为注释行。文件以“Start”开头,以 end 结尾。 Start 之后的字符串是 UserID 然后 nameaddress 将在双引号内。

我需要解析文件并将解析后的数据写入xml文件。

所以生成的文件会像

<ASDF123>
<Name Value="John" />
<Address Value="#6,US" />
</ASDF123>

现在我正在使用模式匹配(正则表达式)来解析上述文件。这是我的示例代码。

    /// <summary>
/// To Store the row data from the file
/// </summary>
List<String> MyList = new List<String>();

String strName = "";
String strAddress = "";
String strInfo = "";

方法:读取文件

    /// <summary>
/// To read the file into a List
/// </summary>
private void ReadFile()
{
StreamReader Reader = new StreamReader(Application.StartupPath + "\\TestFile.txt");
while (!Reader.EndOfStream)
{
MyList.Add(Reader.ReadLine());
}
Reader.Close();
}

方法:FormateRowData

    /// <summary>
/// To remove comments
/// </summary>
private void FormateRowData()
{
MyList = MyList.Where(X => X != "").Where(X => X.StartsWith("--")==false ).ToList();
}

方法:解析数据

    /// <summary>
/// To Parse the data from the List
/// </summary>
private void ParseData()
{
Match l_mMatch;
Regex RegData = new Regex("start[ \t\r\n]*(?<Data>[a-z0-9]*)", RegexOptions.IgnoreCase);
Regex RegName = new Regex("name [ \t\r\n]*\"(?<Name>[a-z]*)\"", RegexOptions.IgnoreCase);
Regex RegAddress = new Regex("address [ \t\r\n]*\"(?<Address>[a-z0-9 #,]*)\"", RegexOptions.IgnoreCase);
for (int Index = 0; Index < MyList.Count; Index++)
{
l_mMatch = RegData.Match(MyList[Index]);
if (l_mMatch.Success)
strInfo = l_mMatch.Groups["Data"].Value;
l_mMatch = RegName.Match(MyList[Index]);
if (l_mMatch.Success)
strName = l_mMatch.Groups["Name"].Value;
l_mMatch = RegAddress.Match(MyList[Index]);
if (l_mMatch.Success)
strAddress = l_mMatch.Groups["Address"].Value;
}
}

方法:写入文件

    /// <summary>
/// To write parsed information into file.
/// </summary>
private void WriteFile()
{
XDocument XD = new XDocument(
new XElement(strInfo,
new XElement("Name",
new XAttribute("Value", strName)),
new XElement("Address",
new XAttribute("Value", strAddress))));
XD.Save(Application.StartupPath + "\\File.xml");
}

我听说过 ParserGenerator

请帮助我使用 lex 和 yacc 编写解析器。这样做的原因是,我现有的解析器(模式匹配)不灵活,而且它不是正确的方法(我认为是这样)。

我如何使用 ParserGenerator(我已经阅读了 Code Project Sample OneCode Project Sample Two 但我仍然对此不熟悉)。请向我推荐一些输出 C# 解析器的解析器生成器。

最佳答案

Gardens Point LEXGardens Point Parser Generator受LEX和YACC的强烈影响,输出C#代码。

您的语法非常简单,我认为您当前的方法很好,但是想要学习“真正”的方法是值得称赞的。 :-) 所以这是我对语法的建议(只是生产规则;这远不是一个完整的例子。实际的 GPPG 文件需要用 C# 代码替换 ... 来构建语法树,并且您需要 token 声明等 - 阅读文档中的 GPPG 示例。您还需要描述 token 的 GPLEX 文件):

/* Your input file is a list of "top level elements" */
TopLevel :
TopLevel TopLevelElement { ... }
| /* (empty) */

/* A top level element is either a comment or a block.
The COMMENT token must be described in the GPLEX file as
any line that starts with -- . */
TopLevelElement:
Block { ... }
| COMMENT { ... }

/* A block starts with the token START (which, in the GPLEX file,
is defined as the string "Start"), continues with some identifier
(the block name), then has a list of elements, and finally the token
END followed by an identifier. If you want to validate that the
END identifier is the same as the START identifier, you can do that
in the C# code that analyses the syntax tree built by GPPG.
The token Identifier is also defined with a regular expression in GPLEX. */
Block:
START Identifier BlockElementList END Identifier { ... }

BlockElementList:
BlockElementList BlockElement { ... }
| /* empty */

BlockElement:
(NAME | ADDRESS) QuotedString { ... }

关于c# - 如何创建解析器(lex/yacc)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5282384/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com