Я делаю программу, которая загружает cfg из файла и использует его для загрузки языков программирования в синтаксическое дерево.
Как правильно определить идентификатор в грамматике без контекста. На данный момент у меня есть такой формат:
IdentifierStart => $l$ | _;
IdentifierChar => "$l$$IdentifierChar$" | "_$IdentifierChar$" | "$i$$IdentifierChar$" | $e$;
Identifier => "$IdentifierStart$$IdentifierChar$" $w$;
Формат:
$l$ = any letter
$e$ = epsilon
$i$ = any integer
$o$ = any operator
$n$ = new line
$w$ = whitespace
$a$ = any atom
Quotes mean the whitespace needs to match the inside of the quotes
Хотя это работает, это неэффективно, потому что создает глубокое дерево, когда каждая буква может оправданно просто быть перечислены рядом друг с другом. Например, Pragma => $n$ "#direct" $w$ $String$;
с правилами:
IdentifierStart => $l$ | _;
IdentifierChar => "$l$$IdentifierChar$" | "_$IdentifierChar$" | "$i$$IdentifierChar$" | $e$;
Identifier => "$IdentifierStart$$IdentifierChar$";
Symbol => $l$ | $i$ | $o$ | \$$Identifier$\$;
Def => $Symbol$ $Def$ | $Symbol$ | "Def";
Assignment => $Def$ \| $Assignment$ | $Def$;
Definition => $Identifier$ "=>" $Assignment$\;;
создает следующее дерево (где каждый пробел представляет уровень в дереве):
Definition:Pragma => $n$ "#pragma" $w$ $String$;
Identifier:Pragma
IdentifierStart:P
Terminal:P
IdentifierChar:ragma
Terminal:r
IdentifierChar:agma
Terminal:a
IdentifierChar:gma
Terminal:g
IdentifierChar:ma
Terminal:m
IdentifierChar:a
Terminal:a
Terminal:=
Terminal:>
Assignment:$n$ "#direct" $w$ $String$
...
Хотя это нормально в В случае идентификатора, я заметил, что возникла проблема, когда я понял, что мне нужно определить формат файла таким же рекурсивным способом:
File => $ValidDirective$ $File$;
ValidDirective => $Comment$ | $Include$ | $Define$ | $Undef$ | $IfPart$ | $Error$ | $Pragma$ | $String$;
Каждый элемент файла будет храниться в поддереве предыдущий элемент! Я не думаю, что это приемлемо, потому что в программе с миллионами строк это будет невероятно неэффективно.
Можно ли как-нибудь исправить эту проблему, оставаясь верным соглашениям CFG?