TL; DR:如何计算一个语法产品的模型,以便为同一个左手边存在不确定数量的产品?
我正在研究一个关于形式语言理论的项目,我正在尝试编写一个用于构建常规语法对象的类,这些对象可以传递给有限状态机。我天真的尝试是创建一个API,为每个允许的输入添加一个生产。我的尝试的精简版本如下(基于正式语法的正式定义G = (N, Σ, P, S)
):
class ContextFreeGrammar:
def __init__(self, variables, alphabet, production_rules, start_variable):
self.variables = variables
self.alphabet = alphabet
self.production_rules = production_rules
self.start_variable = start_variable
def __repr__(self):
return '{}({}, {}, {}, {})'.format(
self.__class__.__name__,
self.variables,
self.alphabet,
self.production_rules,
self.start_variable
)
class RegularGrammar(ContextFreeGrammar):
_regular_expression_grammar = None # TODO
@classmethod
def from_regular_expression(cls, regular_expression):
raise NotImplementedError()
我还没有达到实际编写有限状态自动机或下推自动机的程度。
正则表达式的语法是无上下文的,所以我在WSN中包含了我的定义:
syntax = expression .
expression = term "|" expression .
expression = term .
term = factor repetition term .
term = factor term .
term = .
repetition = "*" .
repetition = "+" .
repetition = "?" .
repetition = "{" nonnegative_integer "," nonnegative_integer "}" .
repetition = "{" nonnegative_integer ",}" .
repetition = "{," nonnegative_integer "}" .
nonnegative_integer = nonzero_arabic_numeral arabic_numerals .
nonnegative_integer = arabic_numeral .
nonzero_arabic_numeral = "1" .
nonzero_arabic_numeral = "2" .
nonzero_arabic_numeral = "3" .
nonzero_arabic_numeral = "4" .
nonzero_arabic_numeral = "5" .
nonzero_arabic_numeral = "6" .
nonzero_arabic_numeral = "7" .
nonzero_arabic_numeral = "8" .
nonzero_arabic_numeral = "9" .
arabic_numeral = nonzero_arabic_numeral .
arabic_numeral = "0" .
arabic_numerals = arabic_numeral .
arabic_numerals = arabic_numeral arabic_numerals .
factor = "(" expression ")" .
factor = character_class .
factor = character .
escaped_character = "\\." .
escaped_character = "\\(" .
escaped_character = "\\)" .
escaped_character = "\\+" .
escaped_character = "\\*" .
escaped_character = "\\?" .
escaped_character = "\\[" .
escaped_character = "\\]" .
escaped_character = "\\\\" .
escaped_character = "\\{" .
escaped_character = "\\}" .
escaped_character = "\\|" .
character -> TODO ;
character_class = TODO .
我可以很容易地看到,我明确地将替换分成单独的作品。我这样做是为了便于实施。但我仍然坚持如何进行角色等等。我希望production_rules
成为从左手边到每个相应右手边的一组地图。但现在这看起来不可行。
答案 0 :(得分:0)
我并不完全理解您的问题,但从评论中看来,您似乎正在尝试在预定义的字符集中工作,该字符集排除了各种Unicode& ASCII字符。
这是我最近为处理类似约束而实现的方法:
以下是实现上述定义的示例:
global rx_Trim_FromAlphaNumeric
rx_Trim_FromAlphaNumeric = \
"[" + rx_AlphaNumeric + "]+" + \
"[" + rx_ValidCharacters_WithLineSpace + "]*"
global rx_StartsWithSymbol
rx_StartsWithSymbol = \
"[^" + rx_AlphaNumeric + "]" + \
"[" + rx_Symbols + "]+" + \
"[" + rx_LineSpace + rx_Symbols + "]*" + \
"[" + rx_AlphaNumeric + "]+" + \
"[" + rx_ValidCharacters_WithLineSpace + "]*"
global rx_StartsWithLetter
rx_StartsWithLetter = \
"^[" + rx_Alphabetic + "]+" + \
"[" + rx_ValidCharacters_WithLineSpace + "]+"
global rx_StartsWithNumber
rx_StartsWithNumber = \
"^[" + rx_Numeric + "]+" + \
"[" + rx_ValidCharacters_WithLineSpace + "]+"
global rx_WordSegments
rx_WordSegments = \
"([" + rx_Symbols + "]+|" + \
"[" + rx_Numeric + "]+|" + \
"[" + rx_Alphabetic + "]+|" + \
"[" + rx_LineSpace + "]+)"
注意: 我更喜欢转义所有符号,因为某些字符(例如^
)具有上下文转义要求。如果它们总是被转义,则不太可能遇到问题。