我尝试记录menuentries.conf
(用于菜单项的配置文件)中使用的语法,方法是使用称为扩展Backus-Naur-Form EBNF()的符号描述语法/语法。 BNF)此menuentries.conf使用缩进级别作为语法组件,如在本示例中应显示的那样:
menu_entry_1
menu_entry_2
menu_entry_2_submenu_entry_1
menu_entry_2_submenu_entry_2
menu_entry_2_submenu_entry_2_subsubmenu_1
menu_entry_2_submenu_entry_2_subsubmenu_2
menu_entry_2_submenu_entry_3
menu_entry_3
menu_entry_3_submenu_entry_1
在上面的示例中,每个条目均由字符串表示,为便于说明,该字符串暗示/指示了其位置。另外,示例应遵循以下规则
我提供BNF的尝试如下:
NEWLINE := '\n' INDENTING := ' ' menu_entry_string := ('a'|'b'|....|'z'|'_'|'0'|'1'|...|'9')+ menu_entries := menu_entry (NEWLINE menuentry)* menu_entry := menu_entry_string (NEWLINE INDENTING menu_entry)* submenu_entry := INDENTING menu_entry_string subsubmenu_entry := INDENTING INDENTING menu_entry_string
因此,我的问题是我对递归声明的概念menu_entry
的不满以及它与submenu_entry
和subsubmenu_entry
的冗余性。
知道python也使用缩进来创建块的概念后,我想查找python语法的BNF /定义(如此处:https://docs.python.org/3/reference/grammar.html),但是却留下了INDENT
和DEDENT
就是语法。
因此,我的问题是: 如何正确地使用EBNF来描述以缩进为分组块的语法/语法? 理想情况下,将不胜感激的一个小例子(或者可能是我尝试的更正)。
在最佳情况下,EBNF将定义nesting-level
中block
的概念,即:submenu_entry为1,subsubmenu_entry ....
答案 0 :(得分:1)
当您需要语言创建者的思想时,您可能会想到程序员。传统上,创建语言有两个部分:
某些语言能够结合语言创建的词汇和句法部分,但是在您的情况下这样做并不是一个好主意,因为语法本身无法单独表达特定缩进的思想。那是您留给词法分析器处理的东西。
下面是BNF语法,其中int day = 25;
int month = 08;
var currentYear = DateTime.Now.Year;
var dateToCompare = new DateTime(currentYear, month, day);
var scheduledDt = "25/08/2018";
var scheduledDate = DateTime.ParseExact(scheduledDt, "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
if(dateToCompare.Date == scheduledDate.Date)
{
//Your logic
}
,STRING
,NEWLINE
和INDENT
都是您的词法分析器生成的最终值:
DEDENT
很简单,对吧?我加入了start ::= list
| list NEWLINE
.
list ::= entry
| list entry
.
entry ::= STRING NEWLINE
| STRING NEWLINE INDENT list DEDENT
.
规则,以确保任何以start
或NEWLINE
标记结尾的文件都是有效的。如果没有它,则以DEDENT
标记结尾而不是NEWLINE
标记的文件将无效。
我使用了BNF,但是如果您愿意的话,也可以轻松地使用EBNF。关键是,词法分析器可以理解使用了多少缩进空间来生成STRING
或INDENT
令牌(如果需要,还可以生成错误),并且语法应简单地指定如何使用令牌生成。