From patchwork Fri Jan 18 11:23:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yang Zhong X-Patchwork-Id: 10769821 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB1341390 for ; Fri, 18 Jan 2019 11:44:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C3D82289BD for ; Fri, 18 Jan 2019 11:44:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B34C928A14; Fri, 18 Jan 2019 11:44:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2206C289BD for ; Fri, 18 Jan 2019 11:44:04 +0000 (UTC) Received: from localhost ([127.0.0.1]:36871 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gkSZ9-000761-C2 for patchwork-qemu-devel@patchwork.kernel.org; Fri, 18 Jan 2019 06:44:03 -0500 Received: from eggs.gnu.org ([209.51.188.92]:36466) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gkSIH-0001EL-MJ for qemu-devel@nongnu.org; Fri, 18 Jan 2019 06:26:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gkSIG-0007G2-4m for qemu-devel@nongnu.org; Fri, 18 Jan 2019 06:26:37 -0500 Received: from mga06.intel.com ([134.134.136.31]:47096) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gkSIF-0006rc-RZ for qemu-devel@nongnu.org; Fri, 18 Jan 2019 06:26:36 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Jan 2019 03:25:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,491,1539673200"; d="scan'208";a="292570797" Received: from he.bj.intel.com ([10.238.157.85]) by orsmga005.jf.intel.com with ESMTP; 18 Jan 2019 03:25:20 -0800 From: Yang Zhong To: qemu-devel@nongnu.org Date: Fri, 18 Jan 2019 19:23:49 +0800 Message-Id: <20190118112410.3010-23-yang.zhong@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190118112410.3010-1-yang.zhong@intel.com> References: <20190118112410.3010-1-yang.zhong@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.31 Subject: [Qemu-devel] [RFC PATCH v3 22/43] minikconfig: add AST X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yang.zhong@intel.com, peter.maydell@linaro.org, thuth@redhat.com, sameo@linux.intel.com, pbonzini@redhat.com, ehabkost@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paolo Bonzini Add Python classes that represent the Kconfig abstract syntax tree. The abstract syntax tree is stored as a list of clauses. For example: config FOO depends on BAR select BAZ is represented as three clauses: FOO depends on BAR FOO default n select BAZ if FOO Signed-off-by: Paolo Bonzini --- scripts/minikconf.py | 116 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/scripts/minikconf.py b/scripts/minikconf.py index fb39e35d6a..a6a28c9c47 100644 --- a/scripts/minikconf.py +++ b/scripts/minikconf.py @@ -26,11 +26,84 @@ __all__ = [ 'KconfigParserError', 'KconfigData', 'KconfigParser' ] # ------------------------------------------- class KconfigData: + class Expr: + def __and__(self, rhs): + return KconfigData.AND(self, rhs) + def __or__(self, rhs): + return KconfigData.OR(self, rhs) + def __invert__(self): + return KconfigData.NOT(self) + + class AND(Expr): + def __init__(self, lhs, rhs): + self.lhs = lhs + self.rhs = rhs + def __str__(self): + return "(%s && %s)" % (self.lhs, self.rhs) + + class OR(Expr): + def __init__(self, lhs, rhs): + self.lhs = lhs + self.rhs = rhs + def __str__(self): + return "(%s || %s)" % (self.lhs, self.rhs) + + class NOT(Expr): + def __init__(self, lhs): + self.lhs = lhs + def __str__(self): + return "!%s" % (self.lhs) + + class Var(Expr): + def __init__(self, name): + self.name = name + self.value = None + def __str__(self): + return self.name + + class Clause: + def __init__(self, dest): + self.dest = dest + + class AssignmentClause(Clause): + def __init__(self, dest, value): + KconfigData.Clause.__init__(self, dest) + self.value = value + def __str__(self): + return "%s=%s" % (self.dest, 'y' if self.value else 'n') + + class DefaultClause(Clause): + def __init__(self, dest, value, cond=None): + KconfigData.Clause.__init__(self, dest) + self.value = value + self.cond = cond + def __str__(self): + value = 'y' if self.value else 'n' + if self.cond is None: + return "config %s default %s" % (self.dest, value) + else: + return "config %s default %s if %s" % (self.dest, value, self.cond) + + class DependsOnClause(Clause): + def __init__(self, dest, expr): + KconfigData.Clause.__init__(self, dest) + self.expr = expr + def __str__(self): + return "config %s depends on %s" % (self.dest, self.expr) + + class SelectClause(Clause): + def __init__(self, dest, cond): + KconfigData.Clause.__init__(self, dest) + self.cond = cond + def __str__(self): + return "select %s if %s" % (self.dest, self.cond) + def __init__(self): self.previously_included = [] self.incl_info = None self.defined_vars = set() - self.referenced_vars = set() + self.referenced_vars = dict() + self.clauses = list() # semantic analysis ------------- @@ -48,26 +121,28 @@ class KconfigData: if (var in self.defined_vars): raise Exception('variable "' + var + '" defined twice') - self.defined_vars.add(var) + self.defined_vars.add(var.name) # var is a string with the variable's name. - # - # For now this just returns the variable's name itself. def do_var(self, var): - self.referenced_vars.add(var) - return var + if (var in self.referenced_vars): + return self.referenced_vars[var] + + var_obj = self.referenced_vars[var] = KconfigData.Var(var) + return var_obj def do_assignment(self, var, val): - pass + self.clauses.append(KconfigData.AssignmentClause(var, val)) def do_default(self, var, val, cond=None): - pass + self.clauses.append(KconfigData.DefaultClause(var, val, cond)) def do_depends_on(self, var, expr): - pass + self.clauses.append(KconfigData.DependsOnClause(var, expr)) def do_select(self, var, symbol, cond=None): - pass + cond = (cond & var) if cond is not None else var + self.clauses.append(KconfigData.SelectClause(symbol, cond)) # ------------------------------------------- # KconfigParser implements a recursive descent parser for (simplified) @@ -227,31 +302,34 @@ class KconfigParser: def parse_primary(self): if self.tok == TOK_NOT: self.get_token() - self.parse_primary() + val = ~self.parse_primary() elif self.tok == TOK_LPAREN: self.get_token() - self.parse_expr() + val = self.parse_expr() if self.tok != TOK_RPAREN: raise KconfigParserError(self, 'Expected ")"') self.get_token() elif self.tok == TOK_ID: - self.parse_var() + val = self.parse_var() else: raise KconfigParserError(self, 'Expected "!" or "(" or identifier') + return val # disj: primary (OR primary)* def parse_disj(self): - self.parse_primary() + lhs = self.parse_primary() while self.tok == TOK_OR: self.get_token() - self.parse_primary() + lhs = lhs | self.parse_primary() + return lhs # expr: disj (AND disj)* def parse_expr(self): - self.parse_disj() + lhs = self.parse_disj() while self.tok == TOK_AND: self.get_token() - self.parse_disj() + lhs = lhs & self.parse_disj() + return lhs # condition: IF expr # | empty @@ -420,4 +498,6 @@ class KconfigParser: if __name__ == '__main__': fname = len(sys.argv) > 1 and sys.argv[1] or 'Kconfig.test' - KconfigParser.parse(open(fname, 'r')) + data = KconfigParser.parse(open(fname, 'r')) + for i in data.clauses: + print i