C的关键字标签值样式配置文件解析库
是否已经存在将读取以下样式文件的配置解析库:C的关键字标签值样式配置文件解析库,c,parsing,configuration-files,C,Parsing,Configuration Files,是否已经存在将读取以下样式文件的配置解析库: 关键字标签值 通过{}替换值进行嵌套;可选标签;支持“Include”就好了 示例配置文件可能如下所示: Listen Inside 127.0.0.1:1000; Listen Outside { IP 1.2.3.4; Port 1000; TLS { CertFile /path/to/file; }; }; ACL default_acl { IP 192.168.0.0/24;
关键字标签值代码>
通过{}
替换值进行嵌套;可选标签;支持“Include”就好了
示例配置文件可能如下所示:
Listen Inside 127.0.0.1:1000;
Listen Outside {
IP 1.2.3.4;
Port 1000;
TLS {
CertFile /path/to/file;
};
};
ACL default_acl {
IP 192.168.0.0/24;
IP 10.0.0.0/24;
};
存在C库的到和。它们看起来就像您所需要的。存在C库的to和。它们看起来像你需要的东西。你看过(或者是flex和bison)吗?这有点毛茸茸的,但我们使用它们来解析与您的配置文件完全相同的文件。您可以使用括号定义子结构,解析具有相同键的可变长度列表,等等
你所说的标签是指评论吗?您可以定义自己的注释结构,我们使用“#”表示注释行
它不支持包含AFAIK。您看过(或者flex和bison)吗?这有点毛茸茸的,但我们使用它们来解析与您的配置文件完全相同的文件。您可以使用括号定义子结构,解析具有相同键的可变长度列表,等等
你所说的标签是指评论吗?您可以定义自己的注释结构,我们使用“#”表示注释行
它不支持包含AFAIK。您熟悉哪些编程语言?你的问题给我的印象是C
您的配置语言的标记似乎是正则表达式:
- 听
- 127.0.0.1:1000
- 一千
- )李>
- {
- }
- 等等
几乎所有现代编程语言都有某种形式的支持
如果实现是C,我可能会使用flex。它生成一个函数,该函数将应用一组正则表达式,将匹配的文本放入一个C字符串中,并返回该正则表达式的类型(只返回一个int,由您选择)。该函数是“词法分析器”或“标记器”。它将字符流分割成符合您需要的方便单位,一次一个正则表达式
Flex非常容易使用。它比lex有几个优点。一个是可以有多个词法分析器函数,因此如果需要对include文件执行一些奇怪的操作,那么可以为该任务使用第二个词法分析器函数
你的语言看起来很简单。野牛/Yacc是非常强大的工具,“强大的力量带来巨大的责任”:-)
我认为它足够简单,我可以手工编写解析器。它可能只有几个函数来处理它的结构。一种非常简单的技术称为递归下降解析器。你有CS学位,或者了解这些东西吗
很多人(在这个阶段)会告诉你去买''或它的一个新版本,通常是因为他们在大学里就是这样的。龙之书很棒,但它就像告诉某人阅读所有维基百科来了解鲸鱼。如果你有时间,你会学到很多
这篇文章是一个合理的开始。递归下降法非常流行,因为它相对容易理解。使它变得简单的事情是有一个适当的语法,它被转换成一种易于递归下降解析的形式。然后,您可以为每个规则编写一个函数,并使用一个简单的错误处理机制(这就是为什么我问这个问题)。可能有工具可以生成它们,但您可能会发现编写它们会更快。第一次割伤可能需要一天的时间,然后你就可以做出决定了
一个非常漂亮的lex/flex特性是,任何不匹配的字符都只是回显到标准输出。因此,您可以查看正则表达式匹配的内容,并可以增量添加它们。当输出“干涸”时,所有内容都被匹配
Pontification alert:IMHO,更多的C程序员应该学会使用flex。它相对容易使用,并且对于文本处理非常强大。IMHO很多人都被推迟了,因为他们还被告知使用yacc/bison,这是一种更强大、更微妙、更复杂的工具。
结束自大
如果你需要一些语法方面的帮助,请询问。如果有一个很好的语法(可能不是这样,但到目前为止,您的示例看起来还不错),那么实现是简单的
我发现了两个指向stackoverflow答案的链接,看起来很有用:
下面是一个使用flex的示例
Flex接受一个“脚本”,并生成一个名为yylex()的C函数。这是输入脚本
请记住,所有正则表达式都在该yylex函数中匹配,因此尽管脚本看起来很奇怪,但它实际上是一个普通的C函数。为了告诉调用方(将是递归下降解析器)匹配的正则表达式类型,它返回一个您选择的整数值,就像任何普通C函数一样
如果没有什么可以告诉解析器的,比如空格,或者某种形式的注释,它就不会返回。它“无声地”消耗这些字符。如果语法需要使用换行符,那么它将被识别为一个标记,并向解析器返回一个合适的标记值。有时更容易让它更自由,因此本例会消耗并忽略所有空白
实际上,yylex函数是从第一个%%
到第二个%%
的所有函数。它的行为类似于一个大的switch()
语句。
正则表达式类似于(非常奇特的)大小写:
标签。
{…}
中的代码是普通C。它可以包含任何C语句,并且必须正确嵌套在{…}
第一个%%
之前的内容是放置flex定义的地方,以及一些flex的“说明”。
%{…%}
中的内容是普通C,可以
/* scanner for a configuration files */
%{
/* Put headers in here */
#include <config.h>
%}
%%
[0-9]+ { return TOK_NUMBER; }
[0-9]+"."[0-9]+"."[0-9]+"."[0-9]+":"[0-9]+ { return TOK_IP_PORT; }
[0-9]+"."[0-9]+"."[0-9]+"."[0-9]+"/"[0-9]+ { return TOK_IP_RANGE; }
"Listen" { return TOK_KEYWORD_LISTEN; }
[A-Za-z][A-Za-z0-9_]* { return TOK_IDENTIFIER; }
"{" { return TOK_OPEN_BRACE; }
"}" { return TOK_CLOSE_BRACE; }
";" { return TOK_SEMICOLON; }
[ \t\n]+ /* eat up whitespace, do nothing */
. { fprintf(stderr, "Unrecognized character: %s\n", yytext );
exit(1);
}
%%
/* -------- A simple test ----------- */
int main(int argc, char *argv[])
{
int tok;
yyin = stdin;
while (tok=yylex()) {
fprintf(stderr, "%d %s\n", tok, yytext);
}
}
flex config.l
gcc lex.yy.c -ll
./a.out <tinytest
#ifndef _CONFIG_H_
#define _CONFIG_H_
enum TOKENS {
TOK_KEYWORD_LISTEN = 256,
TOK_IDENTIFIER = 257,
TOK_OPEN_BRACE = 258,
TOK_CLOSE_BRACE = 259,
TOK_SEMICOLON = 260,
TOK_IP_PORT = 261,
TOK_IP_RANGE = 262,
TOK_NUMBER = 263,
};
#endif _CONFIG_H_