词法分析、语法分析专题

词法分析、语法分析专题

前言:这是字符串解析的大杀器,基本上能推出「上下文无关文法」就能做出这道题

0X00 模板

1096. 花括号展开 II

转:https://leetcode-cn.com/problems/brace-expansion-ii/solution/pythondi-gui-xia-jiang-yu-fa-fen-xi-yi-chong-fan-2/

import re
from collections import namedtuple

token = namedtuple('token', ['type', 'value'])


left = r'(?P\{)'
right = r'(?P\})'
word = r'(?P[a-z]+)'
comma = r'(?P\,)'
blank = r'(?P\s)'
pt = re.compile('|'.join([left, right, word, comma, blank]))


def genToken(s):
    scanner = pt.scanner(s)
    for i in iter(scanner.match, None):
        if i.lastgroup != 'BLANK':
            yield token(i.lastgroup, i.group(0))


class parser:
    '''gramar
        expr -> item | item ',' expr
        item -> factor | factor item
        factor -> WORD | '{' expr '}'
    '''

    def match(self, tp):
        # print(self.p.value)
        if tp == self.p.type:
            val = self.p.value
            try:
                self.p = next(self.gen)
            except StopIteration:
                self.p = None
            except Exception as e:
                print(e)
            return val
        else:
            raise Exception(f"[Error]: {tp} expected, got {self.p.type}")

    def parse(self, s):
        self.gen = genToken(s)
        self.p = next(self.gen)
        st = self.expr()
        return sorted(list(st))

    def expr(self):
        ret = self.item()
        while self.p and self.p.type == 'COMMA':
            self.match('COMMA')
            ret = ret.union(self.item())
        return ret

    def item(self):
        ret = self.factor()
        while self.p and self.p.type in ['WORD', 'LEFT']:
            sufs = self.factor()
            new = set()
            for pre in ret:
                for suf in sufs:
                    new.add(pre+suf)
            ret = new
        return ret

    def factor(self):
        if self.p.type == 'LEFT':
            self.match('LEFT')
            ret = self.expr()
            self.match('RIGHT')
            return ret
        return {self.match('WORD')}


class Solution:
    def braceExpansionII(self, expression):
        return parser().parse(expression)


if __name__ == '__main__':
    sol = Solution()
    li = ["{a,b}{c{d,e}}", "{{a,z}, a{b,c}, {ab,z}}", "{a,b}c{d,e}f"]
    for i in li:
        print('>>>', i)
        print(sol.braceExpansionII(i))

我基本上写完这一套要 20min 哭了。。。

对于「上下文无关文法」的推导的关键是凑反正从 expr 开始,一般两三层可以搞定。

0X01 相关题目

  • 原子的数量

  • 花括号展开2

  • 基本计算器4

  • Lisp 语法解析(这个太难)

  • 394. 字符串解码

你可能感兴趣的:(词法分析、语法分析专题)