From nobody Fri Jun 28 06:11:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548227617822441.7236756747229; Tue, 22 Jan 2019 23:13:37 -0800 (PST) Received: from localhost ([127.0.0.1]:56929 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gmCiw-0006BU-SW for importer@patchew.org; Wed, 23 Jan 2019 02:13:22 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59952) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gmCVq-0004YL-Sc for qemu-devel@nongnu.org; Wed, 23 Jan 2019 01:59:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gmCVp-0003X2-Ns for qemu-devel@nongnu.org; Wed, 23 Jan 2019 01:59:50 -0500 Received: from mga18.intel.com ([134.134.136.126]:36924) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gmCVp-0002Nr-F4 for qemu-devel@nongnu.org; Wed, 23 Jan 2019 01:59:49 -0500 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Jan 2019 22:59:12 -0800 Received: from he.bj.intel.com ([10.238.157.85]) by orsmga001.jf.intel.com with ESMTP; 22 Jan 2019 22:59:10 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,510,1539673200"; d="scan'208";a="129980920" From: Yang Zhong To: qemu-devel@nongnu.org Date: Wed, 23 Jan 2019 14:55:57 +0800 Message-Id: <20190123065618.3520-24-yang.zhong@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190123065618.3520-1-yang.zhong@intel.com> References: <20190123065618.3520-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.126 Subject: [Qemu-devel] [RFC PATCH v4 23/44] 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, ehabkost@redhat.com, pbonzini@redhat.com, sameo@linux.intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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__ =3D [ 'KconfigParserError', 'KconfigData', 'Kco= nfigParser' ] # ------------------------------------------- =20 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 =3D lhs + self.rhs =3D rhs + def __str__(self): + return "(%s && %s)" % (self.lhs, self.rhs) + + class OR(Expr): + def __init__(self, lhs, rhs): + self.lhs =3D lhs + self.rhs =3D rhs + def __str__(self): + return "(%s || %s)" % (self.lhs, self.rhs) + + class NOT(Expr): + def __init__(self, lhs): + self.lhs =3D lhs + def __str__(self): + return "!%s" % (self.lhs) + + class Var(Expr): + def __init__(self, name): + self.name =3D name + self.value =3D None + def __str__(self): + return self.name + + class Clause: + def __init__(self, dest): + self.dest =3D dest + + class AssignmentClause(Clause): + def __init__(self, dest, value): + KconfigData.Clause.__init__(self, dest) + self.value =3D value + def __str__(self): + return "%s=3D%s" % (self.dest, 'y' if self.value else 'n') + + class DefaultClause(Clause): + def __init__(self, dest, value, cond=3DNone): + KconfigData.Clause.__init__(self, dest) + self.value =3D value + self.cond =3D cond + def __str__(self): + value =3D '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, s= elf.cond) + + class DependsOnClause(Clause): + def __init__(self, dest, expr): + KconfigData.Clause.__init__(self, dest) + self.expr =3D 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 =3D cond + def __str__(self): + return "select %s if %s" % (self.dest, self.cond) + def __init__(self): self.previously_included =3D [] self.incl_info =3D None self.defined_vars =3D set() - self.referenced_vars =3D set() + self.referenced_vars =3D dict() + self.clauses =3D list() =20 # semantic analysis ------------- =20 @@ -48,26 +121,28 @@ class KconfigData: if (var in self.defined_vars): raise Exception('variable "' + var + '" defined twice') =20 - self.defined_vars.add(var) + self.defined_vars.add(var.name) =20 # 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 =3D self.referenced_vars[var] =3D KconfigData.Var(var) + return var_obj =20 def do_assignment(self, var, val): - pass + self.clauses.append(KconfigData.AssignmentClause(var, val)) =20 def do_default(self, var, val, cond=3DNone): - pass + self.clauses.append(KconfigData.DefaultClause(var, val, cond)) =20 def do_depends_on(self, var, expr): - pass + self.clauses.append(KconfigData.DependsOnClause(var, expr)) =20 def do_select(self, var, symbol, cond=3DNone): - pass + cond =3D (cond & var) if cond is not None else var + self.clauses.append(KconfigData.SelectClause(symbol, cond)) =20 # ------------------------------------------- # KconfigParser implements a recursive descent parser for (simplified) @@ -227,31 +302,34 @@ class KconfigParser: def parse_primary(self): if self.tok =3D=3D TOK_NOT: self.get_token() - self.parse_primary() + val =3D ~self.parse_primary() elif self.tok =3D=3D TOK_LPAREN: self.get_token() - self.parse_expr() + val =3D self.parse_expr() if self.tok !=3D TOK_RPAREN: raise KconfigParserError(self, 'Expected ")"') self.get_token() elif self.tok =3D=3D TOK_ID: - self.parse_var() + val =3D self.parse_var() else: raise KconfigParserError(self, 'Expected "!" or "(" or identif= ier') + return val =20 # disj: primary (OR primary)* def parse_disj(self): - self.parse_primary() + lhs =3D self.parse_primary() while self.tok =3D=3D TOK_OR: self.get_token() - self.parse_primary() + lhs =3D lhs | self.parse_primary() + return lhs =20 # expr: disj (AND disj)* def parse_expr(self): - self.parse_disj() + lhs =3D self.parse_disj() while self.tok =3D=3D TOK_AND: self.get_token() - self.parse_disj() + lhs =3D lhs & self.parse_disj() + return lhs =20 # condition: IF expr # | empty @@ -420,4 +498,6 @@ class KconfigParser: =20 if __name__ =3D=3D '__main__': fname =3D len(sys.argv) > 1 and sys.argv[1] or 'Kconfig.test' - KconfigParser.parse(open(fname, 'r')) + data =3D KconfigParser.parse(open(fname, 'r')) + for i in data.clauses: + print i --=20 2.17.1