summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgignore1
-rw-r--r--MANIFEST.in2
-rw-r--r--README.html1049
-rw-r--r--README.txt15
-rw-r--r--examples/cdecl.py204
-rw-r--r--pycparser/__init__.py2
-rw-r--r--pycparser/_ast_gen.py495
-rw-r--r--pycparser/_build_tables.py5
-rw-r--r--pycparser/c_ast.py2474
-rw-r--r--pycparser/c_parser.py2681
-rw-r--r--setup.py4
11 files changed, 3477 insertions, 3455 deletions
diff --git a/.hgignore b/.hgignore
index d6574a8..a666b98 100644
--- a/.hgignore
+++ b/.hgignore
@@ -3,6 +3,7 @@ syntax: glob
*.pyc
tests/parser.out
tests/*tab.py
+build
diff --git a/MANIFEST.in b/MANIFEST.in
index 22fa7fb..91b4533 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,6 @@
recursive-include examples *.c *.h *.py
recursive-include tests *.c *.h *.py
-recursive-include pycparser *.py *.yaml
+recursive-include pycparser *.py *.cfg
include utils/*.exe
include utils/fake_libc_include/*.h
include README.*
diff --git a/README.html b/README.html
index 3c4b4ff..3480054 100644
--- a/README.html
+++ b/README.html
@@ -1,523 +1,526 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
-<title>pycparser v2.00</title>
-<meta name="author" content="Eli Bendersky" />
-<style type="text/css">
-
-/*
-:Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 5951 2009-05-18 18:03:10Z milde $
-:Copyright: This stylesheet has been placed in the public domain.
-
-Default cascading style sheet for the HTML output of Docutils.
-
-See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
-customize this style sheet.
-*/
-
-/* used to remove borders from tables and images */
-.borderless, table.borderless td, table.borderless th {
- border: 0 }
-
-table.borderless td, table.borderless th {
- /* Override padding for "table.docutils td" with "! important".
- The right padding separates the table cells. */
- padding: 0 0.5em 0 0 ! important }
-
-.first {
- /* Override more specific margin styles with "! important". */
- margin-top: 0 ! important }
-
-.last, .with-subtitle {
- margin-bottom: 0 ! important }
-
-.hidden {
- display: none }
-
-a.toc-backref {
- text-decoration: none ;
- color: black }
-
-blockquote.epigraph {
- margin: 2em 5em ; }
-
-dl.docutils dd {
- margin-bottom: 0.5em }
-
-/* Uncomment (and remove this text!) to get bold-faced definition list terms
-dl.docutils dt {
- font-weight: bold }
-*/
-
-div.abstract {
- margin: 2em 5em }
-
-div.abstract p.topic-title {
- font-weight: bold ;
- text-align: center }
-
-div.admonition, div.attention, div.caution, div.danger, div.error,
-div.hint, div.important, div.note, div.tip, div.warning {
- margin: 2em ;
- border: medium outset ;
- padding: 1em }
-
-div.admonition p.admonition-title, div.hint p.admonition-title,
-div.important p.admonition-title, div.note p.admonition-title,
-div.tip p.admonition-title {
- font-weight: bold ;
- font-family: sans-serif }
-
-div.attention p.admonition-title, div.caution p.admonition-title,
-div.danger p.admonition-title, div.error p.admonition-title,
-div.warning p.admonition-title {
- color: red ;
- font-weight: bold ;
- font-family: sans-serif }
-
-/* Uncomment (and remove this text!) to get reduced vertical space in
- compound paragraphs.
-div.compound .compound-first, div.compound .compound-middle {
- margin-bottom: 0.5em }
-
-div.compound .compound-last, div.compound .compound-middle {
- margin-top: 0.5em }
-*/
-
-div.dedication {
- margin: 2em 5em ;
- text-align: center ;
- font-style: italic }
-
-div.dedication p.topic-title {
- font-weight: bold ;
- font-style: normal }
-
-div.figure {
- margin-left: 2em ;
- margin-right: 2em }
-
-div.footer, div.header {
- clear: both;
- font-size: smaller }
-
-div.line-block {
- display: block ;
- margin-top: 1em ;
- margin-bottom: 1em }
-
-div.line-block div.line-block {
- margin-top: 0 ;
- margin-bottom: 0 ;
- margin-left: 1.5em }
-
-div.sidebar {
- margin: 0 0 0.5em 1em ;
- border: medium outset ;
- padding: 1em ;
- background-color: #ffffee ;
- width: 40% ;
- float: right ;
- clear: right }
-
-div.sidebar p.rubric {
- font-family: sans-serif ;
- font-size: medium }
-
-div.system-messages {
- margin: 5em }
-
-div.system-messages h1 {
- color: red }
-
-div.system-message {
- border: medium outset ;
- padding: 1em }
-
-div.system-message p.system-message-title {
- color: red ;
- font-weight: bold }
-
-div.topic {
- margin: 2em }
-
-h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
-h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
- margin-top: 0.4em }
-
-h1.title {
- text-align: center }
-
-h2.subtitle {
- text-align: center }
-
-hr.docutils {
- width: 75% }
-
-img.align-left, .figure.align-left{
- clear: left ;
- float: left ;
- margin-right: 1em }
-
-img.align-right, .figure.align-right {
- clear: right ;
- float: right ;
- margin-left: 1em }
-
-.align-left {
- text-align: left }
-
-.align-center {
- clear: both ;
- text-align: center }
-
-.align-right {
- text-align: right }
-
-/* reset inner alignment in figures */
-div.align-right {
- text-align: left }
-
-/* div.align-center * { */
-/* text-align: left } */
-
-ol.simple, ul.simple {
- margin-bottom: 1em }
-
-ol.arabic {
- list-style: decimal }
-
-ol.loweralpha {
- list-style: lower-alpha }
-
-ol.upperalpha {
- list-style: upper-alpha }
-
-ol.lowerroman {
- list-style: lower-roman }
-
-ol.upperroman {
- list-style: upper-roman }
-
-p.attribution {
- text-align: right ;
- margin-left: 50% }
-
-p.caption {
- font-style: italic }
-
-p.credits {
- font-style: italic ;
- font-size: smaller }
-
-p.label {
- white-space: nowrap }
-
-p.rubric {
- font-weight: bold ;
- font-size: larger ;
- color: maroon ;
- text-align: center }
-
-p.sidebar-title {
- font-family: sans-serif ;
- font-weight: bold ;
- font-size: larger }
-
-p.sidebar-subtitle {
- font-family: sans-serif ;
- font-weight: bold }
-
-p.topic-title {
- font-weight: bold }
-
-pre.address {
- margin-bottom: 0 ;
- margin-top: 0 ;
- font: inherit }
-
-pre.literal-block, pre.doctest-block {
- margin-left: 2em ;
- margin-right: 2em }
-
-span.classifier {
- font-family: sans-serif ;
- font-style: oblique }
-
-span.classifier-delimiter {
- font-family: sans-serif ;
- font-weight: bold }
-
-span.interpreted {
- font-family: sans-serif }
-
-span.option {
- white-space: nowrap }
-
-span.pre {
- white-space: pre }
-
-span.problematic {
- color: red }
-
-span.section-subtitle {
- /* font-size relative to parent (h1..h6 element) */
- font-size: 80% }
-
-table.citation {
- border-left: solid 1px gray;
- margin-left: 1px }
-
-table.docinfo {
- margin: 2em 4em }
-
-table.docutils {
- margin-top: 0.5em ;
- margin-bottom: 0.5em }
-
-table.footnote {
- border-left: solid 1px black;
- margin-left: 1px }
-
-table.docutils td, table.docutils th,
-table.docinfo td, table.docinfo th {
- padding-left: 0.5em ;
- padding-right: 0.5em ;
- vertical-align: top }
-
-table.docutils th.field-name, table.docinfo th.docinfo-name {
- font-weight: bold ;
- text-align: left ;
- white-space: nowrap ;
- padding-left: 0 }
-
-h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
-h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
- font-size: 100% }
-
-ul.auto-toc {
- list-style-type: none }
-
-</style>
-</head>
-<body>
-<div class="document" id="pycparser-v2-00">
-<h1 class="title">pycparser v2.00</h1>
-<table class="docinfo" frame="void" rules="none">
-<col class="docinfo-name" />
-<col class="docinfo-content" />
-<tbody valign="top">
-<tr><th class="docinfo-name">Author:</th>
-<td><a class="first reference external" href="http://eli.thegreenplace.net">Eli Bendersky</a></td></tr>
-</tbody>
-</table>
-<div class="contents topic" id="contents">
-<p class="topic-title first">Contents</p>
-<ul class="auto-toc simple">
-<li><a class="reference internal" href="#introduction" id="id2">1&nbsp;&nbsp;&nbsp;Introduction</a><ul class="auto-toc">
-<li><a class="reference internal" href="#what-is-pycparser" id="id3">1.1&nbsp;&nbsp;&nbsp;What is pycparser?</a></li>
-<li><a class="reference internal" href="#what-is-it-good-for" id="id4">1.2&nbsp;&nbsp;&nbsp;What is it good for?</a></li>
-<li><a class="reference internal" href="#which-version-of-c-does-pycparser-support" id="id5">1.3&nbsp;&nbsp;&nbsp;Which version of C does pycparser support?</a></li>
-<li><a class="reference internal" href="#what-grammar-does-pycparser-follow" id="id6">1.4&nbsp;&nbsp;&nbsp;What grammar does pycparser follow?</a></li>
-<li><a class="reference internal" href="#what-is-an-ast" id="id7">1.5&nbsp;&nbsp;&nbsp;What is an AST?</a></li>
-<li><a class="reference internal" href="#how-is-pycparser-licensed" id="id8">1.6&nbsp;&nbsp;&nbsp;How is pycparser licensed?</a></li>
-<li><a class="reference internal" href="#contact-details" id="id9">1.7&nbsp;&nbsp;&nbsp;Contact details</a></li>
-</ul>
-</li>
-<li><a class="reference internal" href="#installing" id="id10">2&nbsp;&nbsp;&nbsp;Installing</a><ul class="auto-toc">
-<li><a class="reference internal" href="#prerequisites" id="id11">2.1&nbsp;&nbsp;&nbsp;Prerequisites</a></li>
-<li><a class="reference internal" href="#installation-process" id="id12">2.2&nbsp;&nbsp;&nbsp;Installation process</a></li>
-</ul>
-</li>
-<li><a class="reference internal" href="#using" id="id13">3&nbsp;&nbsp;&nbsp;Using</a><ul class="auto-toc">
-<li><a class="reference internal" href="#interaction-with-the-c-preprocessor" id="id14">3.1&nbsp;&nbsp;&nbsp;Interaction with the C preprocessor</a></li>
-<li><a class="reference internal" href="#what-about-the-standard-c-library-headers" id="id15">3.2&nbsp;&nbsp;&nbsp;What about the standard C library headers?</a></li>
-<li><a class="reference internal" href="#basic-usage" id="id16">3.3&nbsp;&nbsp;&nbsp;Basic usage</a></li>
-<li><a class="reference internal" href="#advanced-usage" id="id17">3.4&nbsp;&nbsp;&nbsp;Advanced usage</a></li>
-</ul>
-</li>
-<li><a class="reference internal" href="#modifying" id="id18">4&nbsp;&nbsp;&nbsp;Modifying</a></li>
-<li><a class="reference internal" href="#package-contents" id="id19">5&nbsp;&nbsp;&nbsp;Package contents</a></li>
-<li><a class="reference internal" href="#contributors" id="id20">6&nbsp;&nbsp;&nbsp;Contributors</a></li>
-<li><a class="reference internal" href="#changelog" id="id21">7&nbsp;&nbsp;&nbsp;Changelog</a></li>
-</ul>
-</div>
-<div class="section" id="introduction">
-<h1>1&nbsp;&nbsp;&nbsp;Introduction</h1>
-<div class="section" id="what-is-pycparser">
-<h2>1.1&nbsp;&nbsp;&nbsp;What is pycparser?</h2>
-<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> is a parser for the C language, written in pure Python. It is a module designed to be easily integrated into applications that need to parse C source code.</p>
-</div>
-<div class="section" id="what-is-it-good-for">
-<h2>1.2&nbsp;&nbsp;&nbsp;What is it good for?</h2>
-<p>Anything that needs C code to be parsed. The following are some uses for <tt class="docutils literal"><span class="pre">pycparser</span></tt>, taken from real user reports:</p>
-<ul class="simple">
-<li>C code obfuscator</li>
-<li>Front-end for various specialized C compilers</li>
-<li>Static code checker</li>
-<li>Automatic unit-test discovery</li>
-<li>Adding specialized extensions to the C language</li>
-</ul>
-<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> is unique in the sense that it's written in pure Python - a very high level language that's easy to experiment with and tweak. To people familiar with Lex and Yacc, <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s code will be simple to understand.</p>
-</div>
-<div class="section" id="which-version-of-c-does-pycparser-support">
-<h2>1.3&nbsp;&nbsp;&nbsp;Which version of C does pycparser support?</h2>
-<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> aims to support the full C99 language (according to the standard ISO/IEC 9899). This is a new feature in the version 2.x series - earlier versions only supported C89. For more information on the change, read <a class="reference external" href="http://code.google.com/p/pycparser/wiki/C99support">this wiki page</a>.</p>
-<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> doesn't support any GCC extensions.</p>
-</div>
-<div class="section" id="what-grammar-does-pycparser-follow">
-<h2>1.4&nbsp;&nbsp;&nbsp;What grammar does pycparser follow?</h2>
-<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> very closely follows the C grammar provided in the end of the C99 standard document</p>
-</div>
-<div class="section" id="what-is-an-ast">
-<h2>1.5&nbsp;&nbsp;&nbsp;What is an AST?</h2>
-<p><a class="reference external" href="http://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> - Abstract Syntax Tree. It is a tree representation of the syntax of source code - a convenient hierarchical data structure that's built from the code and is readily suitable for exploration and manipulation.</p>
-</div>
-<div class="section" id="how-is-pycparser-licensed">
-<h2>1.6&nbsp;&nbsp;&nbsp;How is pycparser licensed?</h2>
-<p><a class="reference external" href="http://www.gnu.org/licenses/lgpl.html">LGPL</a></p>
-</div>
-<div class="section" id="contact-details">
-<h2>1.7&nbsp;&nbsp;&nbsp;Contact details</h2>
-<p>Drop me an email to <a class="reference external" href="mailto:eliben&#64;gmail.com">eliben&#64;gmail.com</a> for any questions regarding <tt class="docutils literal"><span class="pre">pycparser</span></tt>. For reporting problems with <tt class="docutils literal"><span class="pre">pycparser</span></tt> or submitting feature requests, the best way is to open an issue on the <a class="reference external" href="http://code.google.com/p/pycparser/">pycparser page at Google Code</a>.</p>
-</div>
-</div>
-<div class="section" id="installing">
-<h1>2&nbsp;&nbsp;&nbsp;Installing</h1>
-<div class="section" id="prerequisites">
-<h2>2.1&nbsp;&nbsp;&nbsp;Prerequisites</h2>
-<ul class="simple">
-<li><tt class="docutils literal"><span class="pre">pycparser</span></tt> was tested on Python 2.5, 2.6 and 3.1, on both Linux and Windows</li>
-<li><tt class="docutils literal"><span class="pre">pycparser</span></tt> uses the PLY module for the actual lexer and parser construction. Install PLY version 3.3 (earlier versions work at least since 2.5) from <a class="reference external" href="http://www.dabeaz.com/ply/">its website</a>.</li>
-<li>If you want to modify <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s code, you'll need to install <a class="reference external" href="http://pyyaml.org/">PyYAML</a>, since it's used by <tt class="docutils literal"><span class="pre">pycparser</span></tt> to store the AST configuration in a YAML file.</li>
-</ul>
-</div>
-<div class="section" id="installation-process">
-<h2>2.2&nbsp;&nbsp;&nbsp;Installation process</h2>
-<p>Installing <tt class="docutils literal"><span class="pre">pycparser</span></tt> is very simple. Once you download it from its <a class="reference external" href="http://code.google.com/p/pycparser/">website</a> and unzip the package, you just have to execute the standard <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">install</span></tt>. The setup script will then place the <tt class="docutils literal"><span class="pre">pycparser</span></tt> module into <tt class="docutils literal"><span class="pre">site-packages</span></tt> in your Python's installation library.</p>
-<p>It's recommended to run <tt class="docutils literal"><span class="pre">_build_tables.py</span></tt> in the <tt class="docutils literal"><span class="pre">pycparser</span></tt> code directory to make sure the parsing tables of PLY are pre-generated. This can make your code run faster.</p>
-</div>
-</div>
-<div class="section" id="using">
-<h1>3&nbsp;&nbsp;&nbsp;Using</h1>
-<div class="section" id="interaction-with-the-c-preprocessor">
-<h2>3.1&nbsp;&nbsp;&nbsp;Interaction with the C preprocessor</h2>
-<p>In order to be compilable, C code must be preprocessed by the C preprocessor - <tt class="docutils literal"><span class="pre">cpp</span></tt>. <tt class="docutils literal"><span class="pre">cpp</span></tt> handles preprocessing directives like <tt class="docutils literal"><span class="pre">#include</span></tt> and <tt class="docutils literal"><span class="pre">#define</span></tt>, removes comments, and does other minor tasks that prepare the C code for compilation.</p>
-<p>For all but the most trivial snippets of C code, <tt class="docutils literal"><span class="pre">pycparser</span></tt>, like a C compiler, must receive preprocessed C code in order to function correctly. If you import the top-level <tt class="docutils literal"><span class="pre">parse_file</span></tt> function from the <tt class="docutils literal"><span class="pre">pycparser</span></tt> package, it will interact with <tt class="docutils literal"><span class="pre">cpp</span></tt> for you, as long as it's in your PATH, or you provide a path to it.</p>
-<p>On the vast majority of Linux systems, <tt class="docutils literal"><span class="pre">cpp</span></tt> is installed and is in the PATH. If you're on Windows and don't have <tt class="docutils literal"><span class="pre">cpp</span></tt> somewhere, you can use the one provided in the <tt class="docutils literal"><span class="pre">utils</span></tt> directory in <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s distribution. This <tt class="docutils literal"><span class="pre">cpp</span></tt> executable was compiled from the <a class="reference external" href="http://www.cs.princeton.edu/software/lcc/">LCC distribution</a>, and is provided under LCC's license terms.</p>
-</div>
-<div class="section" id="what-about-the-standard-c-library-headers">
-<h2>3.2&nbsp;&nbsp;&nbsp;What about the standard C library headers?</h2>
-<p>C code almost always includes various header files from the standard C library, like <tt class="docutils literal"><span class="pre">stdio.h</span></tt>. While, with some effort, <tt class="docutils literal"><span class="pre">pycparser</span></tt> can be made to parse the standard headers from any C compiler, it's much simpler to use the provided &quot;fake&quot; standard in includes in <tt class="docutils literal"><span class="pre">utils/fake_libc_include</span></tt>. These are standard C header files that contain only the bare necessities to allow valid parsing of the files that use them. As a bonus, since they're minimal, it can significantly improve the performance of parsing C files.</p>
-<p>See the <tt class="docutils literal"><span class="pre">using_cpp_libc.py</span></tt> example for more details.</p>
-</div>
-<div class="section" id="basic-usage">
-<h2>3.3&nbsp;&nbsp;&nbsp;Basic usage</h2>
-<p>Take a look at the <tt class="docutils literal"><span class="pre">examples</span></tt> directory of the distribution for a few examples of using <tt class="docutils literal"><span class="pre">pycparser</span></tt>. These should be enough to get you started.</p>
-</div>
-<div class="section" id="advanced-usage">
-<h2>3.4&nbsp;&nbsp;&nbsp;Advanced usage</h2>
-<p>The public interface of <tt class="docutils literal"><span class="pre">pycparser</span></tt> is well documented with comments in <tt class="docutils literal"><span class="pre">pycparser/c_parser.py</span></tt>. For a detailed overview of the various AST nodes created by the parser, see <tt class="docutils literal"><span class="pre">pycparser/_c_ast.yaml</span></tt>.</p>
-<p>In any case, you can always drop me an <a class="reference external" href="mailto:eliben&#64;gmail.com">email</a> for help.</p>
-</div>
-</div>
-<div class="section" id="modifying">
-<h1>4&nbsp;&nbsp;&nbsp;Modifying</h1>
-<p>There are a few points to keep in mind when modifying <tt class="docutils literal"><span class="pre">pycparser</span></tt>:</p>
-<ul class="simple">
-<li>The code for <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s AST nodes is automatically generated from a YAML configuration file - <tt class="docutils literal"><span class="pre">_c_ast.yaml</span></tt>, by <tt class="docutils literal"><span class="pre">_ast_gen.py</span></tt>. If you modify the AST configuration, make sure to re-generate the code.</li>
-<li>Make sure you understand the optimized mode of <tt class="docutils literal"><span class="pre">pycparser</span></tt> - for that you must read the docstring in the constructor of the <tt class="docutils literal"><span class="pre">CParser</span></tt> class. For development you should create the parser without optimizations, so that it will regenerate the Yacc and Lex tables when you change the grammar.</li>
-<li>The script <tt class="docutils literal"><span class="pre">_build_tables.py</span></tt> can be helpful - it regenerates all the tables needed by <tt class="docutils literal"><span class="pre">pycparser</span></tt>, and the AST code from YAML.</li>
-</ul>
-</div>
-<div class="section" id="package-contents">
-<h1>5&nbsp;&nbsp;&nbsp;Package contents</h1>
-<p>Once you unzip the <tt class="docutils literal"><span class="pre">pycparser</span></tt> package, you'll see the following files and directories:</p>
-<dl class="docutils">
-<dt>README.txt/html:</dt>
-<dd>This README file.</dd>
-<dt>setup.py:</dt>
-<dd>Installation script</dd>
-<dt>examples/:</dt>
-<dd>A directory with some examples of using <tt class="docutils literal"><span class="pre">pycparser</span></tt></dd>
-<dt>pycparser/:</dt>
-<dd>The <tt class="docutils literal"><span class="pre">pycparser</span></tt> module source code.</dd>
-<dt>tests/:</dt>
-<dd>Unit tests.</dd>
-<dt>utils/cpp.exe:</dt>
-<dd>A Windows executable of the C pre-processor suitable for working with pycparser</dd>
-<dt>utils/fake_libc_include:</dt>
-<dd>Minimal standard C library include files that should allow to parse any C code.</dd>
-<dt>utils/internal/:</dt>
-<dd>Internal utilities for my own use. You probably don't need them.</dd>
-</dl>
-</div>
-<div class="section" id="contributors">
-<h1>6&nbsp;&nbsp;&nbsp;Contributors</h1>
-<p>Some people have contributed to <tt class="docutils literal"><span class="pre">pycparser</span></tt> by opening issues on bugs they've found and/or submitting patches. The list of contributors is at <a class="reference external" href="http://code.google.com/p/pycparser/wiki/Contributors">this pycparser Wiki page</a>.</p>
-</div>
-<div class="section" id="changelog">
-<h1>7&nbsp;&nbsp;&nbsp;Changelog</h1>
-<ul class="simple">
-<li>Version 2.00 (31.10.2010)<ul>
-<li>Support for C99 (read <a class="reference external" href="http://code.google.com/p/pycparser/wiki/C99support">this wiki page</a> for more information).</li>
-</ul>
-</li>
-<li>Version 1.08 (09.10.2010)<ul>
-<li>Bug fixes:<ul>
-<li>Correct handling of <tt class="docutils literal"><span class="pre">do{}</span> <span class="pre">...</span> <span class="pre">while</span></tt> statements in some cases</li>
-<li>Issues 6 &amp; 7: Concatenation of string literals</li>
-<li>Issue 9: Support for unnamed bitfields in structs</li>
-</ul>
-</li>
-</ul>
-</li>
-<li>Version 1.07 (18.05.2010)<ul>
-<li>Python 3.1 compatibility: <tt class="docutils literal"><span class="pre">pycparser</span></tt> was modified to run on Python 3.1 as well as 2.6</li>
-</ul>
-</li>
-<li>Version 1.06 (10.04.2010)<ul>
-<li>Bug fixes:<ul>
-<li>coord not propagated to FuncCall nodes</li>
-<li>lexing of the ^= token (XOREQUALS)</li>
-<li>parsing failed on some abstract declarator rules</li>
-</ul>
-</li>
-<li>Linux compatibility: fixed end-of-line and <tt class="docutils literal"><span class="pre">cpp</span></tt> path issues to allow all tests and examples run on Linux</li>
-</ul>
-</li>
-<li>Version 1.05 (16.10.2009)<ul>
-<li>Fixed the <tt class="docutils literal"><span class="pre">parse_file</span></tt> auxiliary function to handle multiple arguments to <tt class="docutils literal"><span class="pre">cpp</span></tt> correctly</li>
-</ul>
-</li>
-<li>Version 1.04 (22.05.2009)<ul>
-<li>Added the <tt class="docutils literal"><span class="pre">fake_libc_include</span></tt> directory to allow parsing of C code that uses standard C library include files without dependency on a real C library.</li>
-<li>Tested with Python 2.6 and PLY 3.2</li>
-</ul>
-</li>
-<li>Version 1.03 (31.01.2009)<ul>
-<li>Accept enumeration lists with a comma after the last item (C99 feature).</li>
-</ul>
-</li>
-<li>Version 1.02 (16.01.2009)<ul>
-<li>Fixed problem of parsing struct/enum/union names that were named similarly to previously defined <tt class="docutils literal"><span class="pre">typedef</span></tt> types.</li>
-</ul>
-</li>
-<li>Version 1.01 (09.01.2009)<ul>
-<li>Fixed subprocess invocation in the helper function parse_file - now it's more portable</li>
-</ul>
-</li>
-<li>Version 1.0 (15.11.2008)<ul>
-<li>Initial release</li>
-<li>Support for ANSI C89</li>
-</ul>
-</li>
-</ul>
-</div>
-</div>
-</body>
-</html>
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>pycparser v2.01</title>
+<meta name="author" content="Eli Bendersky" />
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 5951 2009-05-18 18:03:10Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+ border: 0 }
+
+table.borderless td, table.borderless th {
+ /* Override padding for "table.docutils td" with "! important".
+ The right padding separates the table cells. */
+ padding: 0 0.5em 0 0 ! important }
+
+.first {
+ /* Override more specific margin styles with "! important". */
+ margin-top: 0 ! important }
+
+.last, .with-subtitle {
+ margin-bottom: 0 ! important }
+
+.hidden {
+ display: none }
+
+a.toc-backref {
+ text-decoration: none ;
+ color: black }
+
+blockquote.epigraph {
+ margin: 2em 5em ; }
+
+dl.docutils dd {
+ margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+ font-weight: bold }
+*/
+
+div.abstract {
+ margin: 2em 5em }
+
+div.abstract p.topic-title {
+ font-weight: bold ;
+ text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+ margin: 2em ;
+ border: medium outset ;
+ padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ font-weight: bold ;
+ font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+ color: red ;
+ font-weight: bold ;
+ font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+ compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+ margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+ margin-top: 0.5em }
+*/
+
+div.dedication {
+ margin: 2em 5em ;
+ text-align: center ;
+ font-style: italic }
+
+div.dedication p.topic-title {
+ font-weight: bold ;
+ font-style: normal }
+
+div.figure {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+div.footer, div.header {
+ clear: both;
+ font-size: smaller }
+
+div.line-block {
+ display: block ;
+ margin-top: 1em ;
+ margin-bottom: 1em }
+
+div.line-block div.line-block {
+ margin-top: 0 ;
+ margin-bottom: 0 ;
+ margin-left: 1.5em }
+
+div.sidebar {
+ margin: 0 0 0.5em 1em ;
+ border: medium outset ;
+ padding: 1em ;
+ background-color: #ffffee ;
+ width: 40% ;
+ float: right ;
+ clear: right }
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+
+div.system-messages {
+ margin: 5em }
+
+div.system-messages h1 {
+ color: red }
+
+div.system-message {
+ border: medium outset ;
+ padding: 1em }
+
+div.system-message p.system-message-title {
+ color: red ;
+ font-weight: bold }
+
+div.topic {
+ margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+ margin-top: 0.4em }
+
+h1.title {
+ text-align: center }
+
+h2.subtitle {
+ text-align: center }
+
+hr.docutils {
+ width: 75% }
+
+img.align-left, .figure.align-left{
+ clear: left ;
+ float: left ;
+ margin-right: 1em }
+
+img.align-right, .figure.align-right {
+ clear: right ;
+ float: right ;
+ margin-left: 1em }
+
+.align-left {
+ text-align: left }
+
+.align-center {
+ clear: both ;
+ text-align: center }
+
+.align-right {
+ text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+ text-align: left }
+
+/* div.align-center * { */
+/* text-align: left } */
+
+ol.simple, ul.simple {
+ margin-bottom: 1em }
+
+ol.arabic {
+ list-style: decimal }
+
+ol.loweralpha {
+ list-style: lower-alpha }
+
+ol.upperalpha {
+ list-style: upper-alpha }
+
+ol.lowerroman {
+ list-style: lower-roman }
+
+ol.upperroman {
+ list-style: upper-roman }
+
+p.attribution {
+ text-align: right ;
+ margin-left: 50% }
+
+p.caption {
+ font-style: italic }
+
+p.credits {
+ font-style: italic ;
+ font-size: smaller }
+
+p.label {
+ white-space: nowrap }
+
+p.rubric {
+ font-weight: bold ;
+ font-size: larger ;
+ color: maroon ;
+ text-align: center }
+
+p.sidebar-title {
+ font-family: sans-serif ;
+ font-weight: bold ;
+ font-size: larger }
+
+p.sidebar-subtitle {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+p.topic-title {
+ font-weight: bold }
+
+pre.address {
+ margin-bottom: 0 ;
+ margin-top: 0 ;
+ font: inherit }
+
+pre.literal-block, pre.doctest-block {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+span.classifier {
+ font-family: sans-serif ;
+ font-style: oblique }
+
+span.classifier-delimiter {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+span.interpreted {
+ font-family: sans-serif }
+
+span.option {
+ white-space: nowrap }
+
+span.pre {
+ white-space: pre }
+
+span.problematic {
+ color: red }
+
+span.section-subtitle {
+ /* font-size relative to parent (h1..h6 element) */
+ font-size: 80% }
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px }
+
+table.docinfo {
+ margin: 2em 4em }
+
+table.docutils {
+ margin-top: 0.5em ;
+ margin-bottom: 0.5em }
+
+table.footnote {
+ border-left: solid 1px black;
+ margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+ padding-left: 0.5em ;
+ padding-right: 0.5em ;
+ vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+ font-weight: bold ;
+ text-align: left ;
+ white-space: nowrap ;
+ padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+ font-size: 100% }
+
+ul.auto-toc {
+ list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="pycparser-v2-01">
+<h1 class="title">pycparser v2.01</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td><a class="first reference external" href="http://eli.thegreenplace.net">Eli Bendersky</a></td></tr>
+</tbody>
+</table>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="auto-toc simple">
+<li><a class="reference internal" href="#introduction" id="id2">1&nbsp;&nbsp;&nbsp;Introduction</a><ul class="auto-toc">
+<li><a class="reference internal" href="#what-is-pycparser" id="id3">1.1&nbsp;&nbsp;&nbsp;What is pycparser?</a></li>
+<li><a class="reference internal" href="#what-is-it-good-for" id="id4">1.2&nbsp;&nbsp;&nbsp;What is it good for?</a></li>
+<li><a class="reference internal" href="#which-version-of-c-does-pycparser-support" id="id5">1.3&nbsp;&nbsp;&nbsp;Which version of C does pycparser support?</a></li>
+<li><a class="reference internal" href="#what-grammar-does-pycparser-follow" id="id6">1.4&nbsp;&nbsp;&nbsp;What grammar does pycparser follow?</a></li>
+<li><a class="reference internal" href="#what-is-an-ast" id="id7">1.5&nbsp;&nbsp;&nbsp;What is an AST?</a></li>
+<li><a class="reference internal" href="#how-is-pycparser-licensed" id="id8">1.6&nbsp;&nbsp;&nbsp;How is pycparser licensed?</a></li>
+<li><a class="reference internal" href="#contact-details" id="id9">1.7&nbsp;&nbsp;&nbsp;Contact details</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#installing" id="id10">2&nbsp;&nbsp;&nbsp;Installing</a><ul class="auto-toc">
+<li><a class="reference internal" href="#prerequisites" id="id11">2.1&nbsp;&nbsp;&nbsp;Prerequisites</a></li>
+<li><a class="reference internal" href="#installation-process" id="id12">2.2&nbsp;&nbsp;&nbsp;Installation process</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#using" id="id13">3&nbsp;&nbsp;&nbsp;Using</a><ul class="auto-toc">
+<li><a class="reference internal" href="#interaction-with-the-c-preprocessor" id="id14">3.1&nbsp;&nbsp;&nbsp;Interaction with the C preprocessor</a></li>
+<li><a class="reference internal" href="#what-about-the-standard-c-library-headers" id="id15">3.2&nbsp;&nbsp;&nbsp;What about the standard C library headers?</a></li>
+<li><a class="reference internal" href="#basic-usage" id="id16">3.3&nbsp;&nbsp;&nbsp;Basic usage</a></li>
+<li><a class="reference internal" href="#advanced-usage" id="id17">3.4&nbsp;&nbsp;&nbsp;Advanced usage</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#modifying" id="id18">4&nbsp;&nbsp;&nbsp;Modifying</a></li>
+<li><a class="reference internal" href="#package-contents" id="id19">5&nbsp;&nbsp;&nbsp;Package contents</a></li>
+<li><a class="reference internal" href="#contributors" id="id20">6&nbsp;&nbsp;&nbsp;Contributors</a></li>
+<li><a class="reference internal" href="#changelog" id="id21">7&nbsp;&nbsp;&nbsp;Changelog</a></li>
+</ul>
+</div>
+<div class="section" id="introduction">
+<h1>1&nbsp;&nbsp;&nbsp;Introduction</h1>
+<div class="section" id="what-is-pycparser">
+<h2>1.1&nbsp;&nbsp;&nbsp;What is pycparser?</h2>
+<p><tt class="docutils literal">pycparser</tt> is a parser for the C language, written in pure Python. It is a module designed to be easily integrated into applications that need to parse C source code.</p>
+</div>
+<div class="section" id="what-is-it-good-for">
+<h2>1.2&nbsp;&nbsp;&nbsp;What is it good for?</h2>
+<p>Anything that needs C code to be parsed. The following are some uses for <tt class="docutils literal">pycparser</tt>, taken from real user reports:</p>
+<ul class="simple">
+<li>C code obfuscator</li>
+<li>Front-end for various specialized C compilers</li>
+<li>Static code checker</li>
+<li>Automatic unit-test discovery</li>
+<li>Adding specialized extensions to the C language</li>
+</ul>
+<p><tt class="docutils literal">pycparser</tt> is unique in the sense that it's written in pure Python - a very high level language that's easy to experiment with and tweak. To people familiar with Lex and Yacc, <tt class="docutils literal">pycparser</tt>'s code will be simple to understand.</p>
+</div>
+<div class="section" id="which-version-of-c-does-pycparser-support">
+<h2>1.3&nbsp;&nbsp;&nbsp;Which version of C does pycparser support?</h2>
+<p><tt class="docutils literal">pycparser</tt> aims to support the full C99 language (according to the standard ISO/IEC 9899). This is a new feature in the version 2.x series - earlier versions only supported C89. For more information on the change, read <a class="reference external" href="http://code.google.com/p/pycparser/wiki/C99support">this wiki page</a>.</p>
+<p><tt class="docutils literal">pycparser</tt> doesn't support any GCC extensions.</p>
+</div>
+<div class="section" id="what-grammar-does-pycparser-follow">
+<h2>1.4&nbsp;&nbsp;&nbsp;What grammar does pycparser follow?</h2>
+<p><tt class="docutils literal">pycparser</tt> very closely follows the C grammar provided in the end of the C99 standard document</p>
+</div>
+<div class="section" id="what-is-an-ast">
+<h2>1.5&nbsp;&nbsp;&nbsp;What is an AST?</h2>
+<p><a class="reference external" href="http://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> - Abstract Syntax Tree. It is a tree representation of the syntax of source code - a convenient hierarchical data structure that's built from the code and is readily suitable for exploration and manipulation.</p>
+</div>
+<div class="section" id="how-is-pycparser-licensed">
+<h2>1.6&nbsp;&nbsp;&nbsp;How is pycparser licensed?</h2>
+<p><a class="reference external" href="http://www.gnu.org/licenses/lgpl.html">LGPL</a></p>
+</div>
+<div class="section" id="contact-details">
+<h2>1.7&nbsp;&nbsp;&nbsp;Contact details</h2>
+<p>Drop me an email to <a class="reference external" href="mailto:eliben&#64;gmail.com">eliben&#64;gmail.com</a> for any questions regarding <tt class="docutils literal">pycparser</tt>. For reporting problems with <tt class="docutils literal">pycparser</tt> or submitting feature requests, the best way is to open an issue on the <a class="reference external" href="http://code.google.com/p/pycparser/">pycparser page at Google Code</a>.</p>
+</div>
+</div>
+<div class="section" id="installing">
+<h1>2&nbsp;&nbsp;&nbsp;Installing</h1>
+<div class="section" id="prerequisites">
+<h2>2.1&nbsp;&nbsp;&nbsp;Prerequisites</h2>
+<ul class="simple">
+<li><tt class="docutils literal">pycparser</tt> was tested on Python 2.5, 2.6 and 3.1, on both Linux and Windows</li>
+<li><tt class="docutils literal">pycparser</tt> uses the PLY module for the actual lexer and parser construction. Install PLY version 3.3 (earlier versions work at least since 2.5) from <a class="reference external" href="http://www.dabeaz.com/ply/">its website</a>.</li>
+</ul>
+</div>
+<div class="section" id="installation-process">
+<h2>2.2&nbsp;&nbsp;&nbsp;Installation process</h2>
+<p>Installing <tt class="docutils literal">pycparser</tt> is very simple. Once you download it from its <a class="reference external" href="http://code.google.com/p/pycparser/">website</a> and unzip the package, you just have to execute the standard <tt class="docutils literal">python setup.py install</tt>. The setup script will then place the <tt class="docutils literal">pycparser</tt> module into <tt class="docutils literal"><span class="pre">site-packages</span></tt> in your Python's installation library.</p>
+<p>It's recommended to run <tt class="docutils literal">_build_tables.py</tt> in the <tt class="docutils literal">pycparser</tt> code directory after installation to make sure the parsing tables of PLY are pre-generated. This can make your code run faster.</p>
+</div>
+</div>
+<div class="section" id="using">
+<h1>3&nbsp;&nbsp;&nbsp;Using</h1>
+<div class="section" id="interaction-with-the-c-preprocessor">
+<h2>3.1&nbsp;&nbsp;&nbsp;Interaction with the C preprocessor</h2>
+<p>In order to be compilable, C code must be preprocessed by the C preprocessor - <tt class="docutils literal">cpp</tt>. <tt class="docutils literal">cpp</tt> handles preprocessing directives like <tt class="docutils literal">#include</tt> and <tt class="docutils literal">#define</tt>, removes comments, and does other minor tasks that prepare the C code for compilation.</p>
+<p>For all but the most trivial snippets of C code, <tt class="docutils literal">pycparser</tt>, like a C compiler, must receive preprocessed C code in order to function correctly. If you import the top-level <tt class="docutils literal">parse_file</tt> function from the <tt class="docutils literal">pycparser</tt> package, it will interact with <tt class="docutils literal">cpp</tt> for you, as long as it's in your PATH, or you provide a path to it.</p>
+<p>On the vast majority of Linux systems, <tt class="docutils literal">cpp</tt> is installed and is in the PATH. If you're on Windows and don't have <tt class="docutils literal">cpp</tt> somewhere, you can use the one provided in the <tt class="docutils literal">utils</tt> directory in <tt class="docutils literal">pycparser</tt>'s distribution. This <tt class="docutils literal">cpp</tt> executable was compiled from the <a class="reference external" href="http://www.cs.princeton.edu/software/lcc/">LCC distribution</a>, and is provided under LCC's license terms.</p>
+</div>
+<div class="section" id="what-about-the-standard-c-library-headers">
+<h2>3.2&nbsp;&nbsp;&nbsp;What about the standard C library headers?</h2>
+<p>C code almost always includes various header files from the standard C library, like <tt class="docutils literal">stdio.h</tt>. While, with some effort, <tt class="docutils literal">pycparser</tt> can be made to parse the standard headers from any C compiler, it's much simpler to use the provided &quot;fake&quot; standard in includes in <tt class="docutils literal">utils/fake_libc_include</tt>. These are standard C header files that contain only the bare necessities to allow valid parsing of the files that use them. As a bonus, since they're minimal, it can significantly improve the performance of parsing C files.</p>
+<p>See the <tt class="docutils literal">using_cpp_libc.py</tt> example for more details.</p>
+</div>
+<div class="section" id="basic-usage">
+<h2>3.3&nbsp;&nbsp;&nbsp;Basic usage</h2>
+<p>Take a look at the <tt class="docutils literal">examples</tt> directory of the distribution for a few examples of using <tt class="docutils literal">pycparser</tt>. These should be enough to get you started.</p>
+</div>
+<div class="section" id="advanced-usage">
+<h2>3.4&nbsp;&nbsp;&nbsp;Advanced usage</h2>
+<p>The public interface of <tt class="docutils literal">pycparser</tt> is well documented with comments in <tt class="docutils literal">pycparser/c_parser.py</tt>. For a detailed overview of the various AST nodes created by the parser, see <tt class="docutils literal">pycparser/_c_ast.cfg</tt>.</p>
+<p>In any case, you can always drop me an <a class="reference external" href="mailto:eliben&#64;gmail.com">email</a> for help.</p>
+</div>
+</div>
+<div class="section" id="modifying">
+<h1>4&nbsp;&nbsp;&nbsp;Modifying</h1>
+<p>There are a few points to keep in mind when modifying <tt class="docutils literal">pycparser</tt>:</p>
+<ul class="simple">
+<li>The code for <tt class="docutils literal">pycparser</tt>'s AST nodes is automatically generated from a configuration file - <tt class="docutils literal">_c_ast.cfg</tt>, by <tt class="docutils literal">_ast_gen.py</tt>. If you modify the AST configuration, make sure to re-generate the code.</li>
+<li>Make sure you understand the optimized mode of <tt class="docutils literal">pycparser</tt> - for that you must read the docstring in the constructor of the <tt class="docutils literal">CParser</tt> class. For development you should create the parser without optimizations, so that it will regenerate the Yacc and Lex tables when you change the grammar.</li>
+</ul>
+</div>
+<div class="section" id="package-contents">
+<h1>5&nbsp;&nbsp;&nbsp;Package contents</h1>
+<p>Once you unzip the <tt class="docutils literal">pycparser</tt> package, you'll see the following files and directories:</p>
+<dl class="docutils">
+<dt>README.txt/html:</dt>
+<dd>This README file.</dd>
+<dt>setup.py:</dt>
+<dd>Installation script</dd>
+<dt>examples/:</dt>
+<dd>A directory with some examples of using <tt class="docutils literal">pycparser</tt></dd>
+<dt>pycparser/:</dt>
+<dd>The <tt class="docutils literal">pycparser</tt> module source code.</dd>
+<dt>tests/:</dt>
+<dd>Unit tests.</dd>
+<dt>utils/cpp.exe:</dt>
+<dd>A Windows executable of the C pre-processor suitable for working with pycparser</dd>
+<dt>utils/fake_libc_include:</dt>
+<dd>Minimal standard C library include files that should allow to parse any C code.</dd>
+<dt>utils/internal/:</dt>
+<dd>Internal utilities for my own use. You probably don't need them.</dd>
+</dl>
+</div>
+<div class="section" id="contributors">
+<h1>6&nbsp;&nbsp;&nbsp;Contributors</h1>
+<p>Some people have contributed to <tt class="docutils literal">pycparser</tt> by opening issues on bugs they've found and/or submitting patches. The list of contributors is at <a class="reference external" href="http://code.google.com/p/pycparser/wiki/Contributors">this pycparser Wiki page</a>.</p>
+</div>
+<div class="section" id="changelog">
+<h1>7&nbsp;&nbsp;&nbsp;Changelog</h1>
+<ul class="simple">
+<li>Version 2.01 (04.12.2010)<ul>
+<li>Removed dependency on YAML. Parsing of the AST node configuration file is done with a simple parser.</li>
+<li>Fixed issue 12: installation problems</li>
+</ul>
+</li>
+<li>Version 2.00 (31.10.2010)<ul>
+<li>Support for C99 (read <a class="reference external" href="http://code.google.com/p/pycparser/wiki/C99support">this wiki page</a> for more information).</li>
+</ul>
+</li>
+<li>Version 1.08 (09.10.2010)<ul>
+<li>Bug fixes:<ul>
+<li>Correct handling of <tt class="docutils literal">do{} ... while</tt> statements in some cases</li>
+<li>Issues 6 &amp; 7: Concatenation of string literals</li>
+<li>Issue 9: Support for unnamed bitfields in structs</li>
+</ul>
+</li>
+</ul>
+</li>
+<li>Version 1.07 (18.05.2010)<ul>
+<li>Python 3.1 compatibility: <tt class="docutils literal">pycparser</tt> was modified to run on Python 3.1 as well as 2.6</li>
+</ul>
+</li>
+<li>Version 1.06 (10.04.2010)<ul>
+<li>Bug fixes:<ul>
+<li>coord not propagated to FuncCall nodes</li>
+<li>lexing of the ^= token (XOREQUALS)</li>
+<li>parsing failed on some abstract declarator rules</li>
+</ul>
+</li>
+<li>Linux compatibility: fixed end-of-line and <tt class="docutils literal">cpp</tt> path issues to allow all tests and examples run on Linux</li>
+</ul>
+</li>
+<li>Version 1.05 (16.10.2009)<ul>
+<li>Fixed the <tt class="docutils literal">parse_file</tt> auxiliary function to handle multiple arguments to <tt class="docutils literal">cpp</tt> correctly</li>
+</ul>
+</li>
+<li>Version 1.04 (22.05.2009)<ul>
+<li>Added the <tt class="docutils literal">fake_libc_include</tt> directory to allow parsing of C code that uses standard C library include files without dependency on a real C library.</li>
+<li>Tested with Python 2.6 and PLY 3.2</li>
+</ul>
+</li>
+<li>Version 1.03 (31.01.2009)<ul>
+<li>Accept enumeration lists with a comma after the last item (C99 feature).</li>
+</ul>
+</li>
+<li>Version 1.02 (16.01.2009)<ul>
+<li>Fixed problem of parsing struct/enum/union names that were named similarly to previously defined <tt class="docutils literal">typedef</tt> types.</li>
+</ul>
+</li>
+<li>Version 1.01 (09.01.2009)<ul>
+<li>Fixed subprocess invocation in the helper function parse_file - now it's more portable</li>
+</ul>
+</li>
+<li>Version 1.0 (15.11.2008)<ul>
+<li>Initial release</li>
+<li>Support for ANSI C89</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+</body>
+</html>
diff --git a/README.txt b/README.txt
index 6b795c9..69eff24 100644
--- a/README.txt
+++ b/README.txt
@@ -1,5 +1,5 @@
===============
-pycparser v2.00
+pycparser v2.01
===============
:Author: `Eli Bendersky <http://eli.thegreenplace.net>`_
@@ -70,14 +70,13 @@ Prerequisites
* ``pycparser`` was tested on Python 2.5, 2.6 and 3.1, on both Linux and Windows
* ``pycparser`` uses the PLY module for the actual lexer and parser construction. Install PLY version 3.3 (earlier versions work at least since 2.5) from `its website <http://www.dabeaz.com/ply/>`_.
-* If you want to modify ``pycparser``'s code, you'll need to install `PyYAML <http://pyyaml.org/>`_, since it's used by ``pycparser`` to store the AST configuration in a YAML file.
Installation process
--------------------
Installing ``pycparser`` is very simple. Once you download it from its `website <http://code.google.com/p/pycparser/>`_ and unzip the package, you just have to execute the standard ``python setup.py install``. The setup script will then place the ``pycparser`` module into ``site-packages`` in your Python's installation library.
-It's recommended to run ``_build_tables.py`` in the ``pycparser`` code directory to make sure the parsing tables of PLY are pre-generated. This can make your code run faster.
+It's recommended to run ``_build_tables.py`` in the ``pycparser`` code directory after installation to make sure the parsing tables of PLY are pre-generated. This can make your code run faster.
Using
@@ -107,7 +106,7 @@ Take a look at the ``examples`` directory of the distribution for a few examples
Advanced usage
--------------
-The public interface of ``pycparser`` is well documented with comments in ``pycparser/c_parser.py``. For a detailed overview of the various AST nodes created by the parser, see ``pycparser/_c_ast.yaml``.
+The public interface of ``pycparser`` is well documented with comments in ``pycparser/c_parser.py``. For a detailed overview of the various AST nodes created by the parser, see ``pycparser/_c_ast.cfg``.
In any case, you can always drop me an `email <eliben@gmail.com>`_ for help.
@@ -116,9 +115,8 @@ Modifying
There are a few points to keep in mind when modifying ``pycparser``:
-* The code for ``pycparser``'s AST nodes is automatically generated from a YAML configuration file - ``_c_ast.yaml``, by ``_ast_gen.py``. If you modify the AST configuration, make sure to re-generate the code.
+* The code for ``pycparser``'s AST nodes is automatically generated from a configuration file - ``_c_ast.cfg``, by ``_ast_gen.py``. If you modify the AST configuration, make sure to re-generate the code.
* Make sure you understand the optimized mode of ``pycparser`` - for that you must read the docstring in the constructor of the ``CParser`` class. For development you should create the parser without optimizations, so that it will regenerate the Yacc and Lex tables when you change the grammar.
-* The script ``_build_tables.py`` can be helpful - it regenerates all the tables needed by ``pycparser``, and the AST code from YAML.
Package contents
@@ -158,6 +156,11 @@ Some people have contributed to ``pycparser`` by opening issues on bugs they've
Changelog
=========
++ Version 2.01 (04.12.2010)
+
+ * Removed dependency on YAML. Parsing of the AST node configuration file is done with a simple parser.
+ * Fixed issue 12: installation problems
+
+ Version 2.00 (31.10.2010)
* Support for C99 (read `this wiki page <http://code.google.com/p/pycparser/wiki/C99support>`_ for more information).
diff --git a/examples/cdecl.py b/examples/cdecl.py
index 3df6efc..23148f8 100644
--- a/examples/cdecl.py
+++ b/examples/cdecl.py
@@ -1,108 +1,108 @@
-#-----------------------------------------------------------------
-# pycparser: cdecl.py
-#
-# Example of the CDECL tool using pycparser. CDECL "explains"
-# C type declarations in plain English.
-#
-# The AST generated by pycparser from the given declaration is
-# traversed recursively to build the explanation.
-# Note that the declaration must be a valid external declaration
-# in C. All the types used in it must be defined with typedef,
-# or parsing will fail. The definition can be arbitrary, it isn't
-# really used - by pycparser must know which tokens are types.
-#
-# For example:
-#
-# 'typedef int Node; const Node* (*ar)[10];'
-# =>
-# ar is a pointer to array[10] of pointer to const Node
-#
-# Copyright (C) 2008-2010, Eli Bendersky
-# License: LGPL
-#-----------------------------------------------------------------
-import sys
-
-# This is not required if you've installed pycparser into
-# your site-packages/ with setup.py
-#
-sys.path.insert(0, '..')
-
-from pycparser import c_parser, c_ast
-from pycparser.portability import printme
-
-
+#-----------------------------------------------------------------
+# pycparser: cdecl.py
+#
+# Example of the CDECL tool using pycparser. CDECL "explains"
+# C type declarations in plain English.
+#
+# The AST generated by pycparser from the given declaration is
+# traversed recursively to build the explanation.
+# Note that the declaration must be a valid external declaration
+# in C. All the types used in it must be defined with typedef,
+# or parsing will fail. The definition can be arbitrary, it isn't
+# really used - by pycparser must know which tokens are types.
+#
+# For example:
+#
+# 'typedef int Node; const Node* (*ar)[10];'
+# =>
+# ar is a pointer to array[10] of pointer to const Node
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+import sys
+
+# This is not required if you've installed pycparser into
+# your site-packages/ with setup.py
+#
+sys.path.insert(0, '..')
+
+from pycparser import c_parser, c_ast
+
+
def explain_c_declaration(c_decl):
- """ Parses the declaration in c_decl and returns a text
- explanation as a string.
-
- The last external node of the string is used, to allow
+ """ Parses the declaration in c_decl and returns a text
+ explanation as a string.
+
+ The last external node of the string is used, to allow
earlier typedefs for used types.
- """
- parser = c_parser.CParser()
-
- try:
- node = parser.parse(c_decl, filename='<stdin>')
- except c_parser.ParseError:
- e = sys.exc_info()[1]
- return "Parse error:" + str(e)
-
- if ( not isinstance(node, c_ast.FileAST) or
- not isinstance(node.ext[-1], c_ast.Decl)):
- return "Not a valid declaration"
-
- return _explain_decl_node(node.ext[-1])
-
-
+ """
+ parser = c_parser.CParser()
+
+ try:
+ node = parser.parse(c_decl, filename='<stdin>')
+ except c_parser.ParseError:
+ e = sys.exc_info()[1]
+ return "Parse error:" + str(e)
+
+ if ( not isinstance(node, c_ast.FileAST) or
+ not isinstance(node.ext[-1], c_ast.Decl)):
+ return "Not a valid declaration"
+
+ return _explain_decl_node(node.ext[-1])
+
+
def _explain_decl_node(decl_node):
- """ Receives a c_ast.Decl note and returns its explanation in
+ """ Receives a c_ast.Decl note and returns its explanation in
English.
- """
- #~ print decl_node.show()
- storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else ''
-
- return (decl_node.name +
- " is a " +
- storage +
- _explain_type(decl_node.type))
-
-
+ """
+ #~ print decl_node.show()
+ storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else ''
+
+ return (decl_node.name +
+ " is a " +
+ storage +
+ _explain_type(decl_node.type))
+
+
def _explain_type(decl):
""" Recursively explains a type decl node
- """
- typ = type(decl)
-
- if typ == c_ast.TypeDecl:
- quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
- return quals + _explain_type(decl.type)
- elif typ == c_ast.Typename or typ == c_ast.Decl:
- return _explain_type(decl.type)
- elif typ == c_ast.IdentifierType:
- return ' '.join(decl.names)
- elif typ == c_ast.PtrDecl:
- quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
- return quals + 'pointer to ' + _explain_type(decl.type)
- elif typ == c_ast.ArrayDecl:
- arr = 'array'
- if decl.dim: arr += '[%s]' % decl.dim.value
-
- return arr + " of " + _explain_type(decl.type)
-
- elif typ == c_ast.FuncDecl:
- if decl.args:
- params = [_explain_type(param) for param in decl.args.params]
- args = ', '.join(params)
- else:
- args = ''
-
- return ('function(%s) returning ' % (args) +
- _explain_type(decl.type))
-
-
-if __name__ == "__main__":
- if len(sys.argv) > 1:
- c_decl = sys.argv[1]
- else:
- c_decl = "char *(*(**foo[][8])())[];"
-
- printme(["Explaining the declaration:", c_decl])
- printme(["\n", explain_c_declaration(c_decl)])
+ """
+ typ = type(decl)
+
+ if typ == c_ast.TypeDecl:
+ quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
+ return quals + _explain_type(decl.type)
+ elif typ == c_ast.Typename or typ == c_ast.Decl:
+ return _explain_type(decl.type)
+ elif typ == c_ast.IdentifierType:
+ return ' '.join(decl.names)
+ elif typ == c_ast.PtrDecl:
+ quals = ' '.join(decl.quals) + ' ' if decl.quals else ''
+ return quals + 'pointer to ' + _explain_type(decl.type)
+ elif typ == c_ast.ArrayDecl:
+ arr = 'array'
+ if decl.dim: arr += '[%s]' % decl.dim.value
+
+ return arr + " of " + _explain_type(decl.type)
+
+ elif typ == c_ast.FuncDecl:
+ if decl.args:
+ params = [_explain_type(param) for param in decl.args.params]
+ args = ', '.join(params)
+ else:
+ args = ''
+
+ return ('function(%s) returning ' % (args) +
+ _explain_type(decl.type))
+
+
+if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ c_decl = sys.argv[1]
+ else:
+ c_decl = "char *(*(**foo[][8])())[];"
+
+ print("Explaining the declaration: " + c_decl + "\n")
+ print(explain_c_declaration(c_decl) + "\n")
+
diff --git a/pycparser/__init__.py b/pycparser/__init__.py
index 7d91134..a51239b 100644
--- a/pycparser/__init__.py
+++ b/pycparser/__init__.py
@@ -9,7 +9,7 @@
#-----------------------------------------------------------------
__all__ = ['c_lexer', 'c_parser', 'c_ast']
-__version__ = '2.00'
+__version__ = '2.01'
from subprocess import Popen, PIPE
diff --git a/pycparser/_ast_gen.py b/pycparser/_ast_gen.py
index 68904d1..2bef0fb 100644
--- a/pycparser/_ast_gen.py
+++ b/pycparser/_ast_gen.py
@@ -1,249 +1,264 @@
-#-----------------------------------------------------------------
-# _ast_gen.py
-#
-# Generates the AST Node classes from a specification given in
-# a .yaml file
-#
-# The design of this module was inspired by astgen.py from the
-# Python 2.5 code-base.
-#
-# Copyright (C) 2008-2010, Eli Bendersky
-# License: LGPL
-#-----------------------------------------------------------------
-
-import pprint
-from string import Template
-
-import yaml
-
-
+#-----------------------------------------------------------------
+# _ast_gen.py
+#
+# Generates the AST Node classes from a specification given in
+# a .yaml file
+#
+# The design of this module was inspired by astgen.py from the
+# Python 2.5 code-base.
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+import pprint
+from string import Template
+
+
class ASTCodeGenerator(object):
- def __init__(self, cfg_filename='_c_ast.yaml'):
- """ Initialize the code generator from a configuration
+ def __init__(self, cfg_filename='_c_ast.cfg'):
+ """ Initialize the code generator from a configuration
file.
- """
- self.cfg_filename = cfg_filename
- cfg = yaml.load(open(cfg_filename).read())
- self.node_cfg = [NodeCfg(name, cfg[name]) for name in cfg]
-
- #~ pprint.pprint(self.node_cfg)
- #~ print ''
-
- def generate(self, file=None):
- """ Generates the code into file, an open file buffer.
- """
- src = Template(_PROLOGUE_COMMENT).substitute(
- cfg_filename=self.cfg_filename)
-
- src += _PROLOGUE_CODE
- for node_cfg in self.node_cfg:
- src += node_cfg.generate_source() + '\n\n'
-
+ """
+ self.cfg_filename = cfg_filename
+ self.node_cfg = [NodeCfg(name, contents) for (name, contents) in self.parse_cfgfile(cfg_filename)]
+
+ def generate(self, file=None):
+ """ Generates the code into file, an open file buffer.
+ """
+ src = Template(_PROLOGUE_COMMENT).substitute(
+ cfg_filename=self.cfg_filename)
+
+ src += _PROLOGUE_CODE
+ for node_cfg in self.node_cfg:
+ src += node_cfg.generate_source() + '\n\n'
+
file.write(src)
-
-
+
+ def parse_cfgfile(self, filename):
+ """ Parse the configuration file and yield pairs of
+ (name, contents) for each node.
+ """
+ with open(filename, "r") as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ colon_i = line.find(':')
+ lbracket_i = line.find('[')
+ rbracket_i = line.find(']')
+ if colon_i < 1 or lbracket_i <= colon_i or rbracket_i <= lbracket_i:
+ raise RuntimeError("Invalid line in %s:\n%s\n" % (filename, line))
+
+ name = line[:colon_i]
+ val = line[lbracket_i + 1:rbracket_i]
+ vallist = [v.strip() for v in val.split(',')] if val else []
+ yield name, vallist
+
+
class NodeCfg(object):
- def __init__(self, name, contents):
- self.name = name
- self.all_entries = []
- self.attr = []
- self.child = []
- self.seq_child = []
-
- for entry in contents:
- clean_entry = entry.rstrip('*')
- self.all_entries.append(clean_entry)
-
- if entry.endswith('**'):
- self.seq_child.append(clean_entry)
- elif entry.endswith('*'):
- self.child.append(clean_entry)
- else:
+ """ Node configuration.
+
+ name: node name
+ contents: a list of contents - attributes and child nodes
+ See comment at the top of the configuration file for details.
+ """
+ def __init__(self, name, contents):
+ self.name = name
+ self.all_entries = []
+ self.attr = []
+ self.child = []
+ self.seq_child = []
+
+ for entry in contents:
+ clean_entry = entry.rstrip('*')
+ self.all_entries.append(clean_entry)
+
+ if entry.endswith('**'):
+ self.seq_child.append(clean_entry)
+ elif entry.endswith('*'):
+ self.child.append(clean_entry)
+ else:
self.attr.append(entry)
-
+
def generate_source(self):
- src = self._gen_init()
- src += '\n' + self._gen_children()
- src += '\n' + self._gen_show()
- return src
-
+ src = self._gen_init()
+ src += '\n' + self._gen_children()
+ src += '\n' + self._gen_show()
+ return src
+
def _gen_init(self):
- src = "class %s(Node):\n" % self.name
-
- if self.all_entries:
- args = ', '.join(self.all_entries)
- arglist = '(self, %s, coord=None)' % args
- else:
- arglist = '(self, coord=None)'
-
- src += " def __init__%s:\n" % arglist
-
- for name in self.all_entries + ['coord']:
- src += " self.%s = %s\n" % (name, name)
-
- return src
-
+ src = "class %s(Node):\n" % self.name
+
+ if self.all_entries:
+ args = ', '.join(self.all_entries)
+ arglist = '(self, %s, coord=None)' % args
+ else:
+ arglist = '(self, coord=None)'
+
+ src += " def __init__%s:\n" % arglist
+
+ for name in self.all_entries + ['coord']:
+ src += " self.%s = %s\n" % (name, name)
+
+ return src
+
def _gen_children(self):
- src = ' def children(self):\n'
-
- if self.all_entries:
- src += ' nodelist = []\n'
-
- template = ('' +
- ' if self.%s is not None:' +
- ' nodelist.%s(self.%s)\n')
-
- for child in self.child:
- src += template % (
- child, 'append', child)
-
- for seq_child in self.seq_child:
- src += template % (
- seq_child, 'extend', seq_child)
-
- src += ' return tuple(nodelist)\n'
- else:
- src += ' return ()\n'
-
- return src
-
+ src = ' def children(self):\n'
+
+ if self.all_entries:
+ src += ' nodelist = []\n'
+
+ template = ('' +
+ ' if self.%s is not None:' +
+ ' nodelist.%s(self.%s)\n')
+
+ for child in self.child:
+ src += template % (
+ child, 'append', child)
+
+ for seq_child in self.seq_child:
+ src += template % (
+ seq_child, 'extend', seq_child)
+
+ src += ' return tuple(nodelist)\n'
+ else:
+ src += ' return ()\n'
+
+ return src
+
def _gen_show(self):
- src = ' def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):\n'
- src += " lead = ' ' * offset\n"
-
- src += " buf.write(lead + '%s: ')\n\n" % self.name
-
- if self.attr:
- src += " if attrnames:\n"
- src += " attrstr = ', '.join('%s=%s' % nv for nv in ["
- src += ', '.join('("%s", repr(%s))' % (nv, 'self.%s' % nv) for nv in self.attr)
- src += '])\n'
- src += " else:\n"
- src += " attrstr = ', '.join('%s' % v for v in ["
- src += ', '.join('self.%s' % v for v in self.attr)
- src += '])\n'
- src += " buf.write(attrstr)\n\n"
-
- src += " if showcoord:\n"
- src += " buf.write(' (at %s)' % self.coord)\n"
- src += " buf.write('\\n')\n\n"
-
- src += " for c in self.children():\n"
- src += " c.show(buf, offset + 2, attrnames, showcoord)\n"
-
- return src
-
-
-_PROLOGUE_COMMENT = \
-r'''#-----------------------------------------------------------------
-# ** ATTENTION **
-# This code was automatically generated from the file:
-# $cfg_filename
-#
-# Do not modify it directly. Modify the configuration file and
-# run the generator again.
-# ** ** *** ** **
-#
-# pycparser: c_ast.py
-#
-# AST Node classes.
-#
-# Copyright (C) 2008, Eli Bendersky
-# License: LGPL
-#-----------------------------------------------------------------
-
-'''
-
-_PROLOGUE_CODE = r'''
-import sys
-
-
-class Node(object):
- """ Abstract base class for AST nodes.
- """
- def children(self):
- """ A sequence of all children that are Nodes
- """
- pass
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- """ Pretty print the Node and all its attributes and
- children (recursively) to a buffer.
-
- file:
- Open IO buffer into which the Node is printed.
-
- offset:
- Initial offset (amount of leading spaces)
-
- attrnames:
- True if you want to see the attribute names in
- name=value pairs. False to only see the values.
-
- showcoord:
- Do you want the coordinates of each Node to be
- displayed.
- """
- pass
-
-
-class NodeVisitor(object):
- """ A base NodeVisitor class for visiting c_ast nodes.
- Subclass it and define your own visit_XXX methods, where
- XXX is the class name you want to visit with these
- methods.
-
- For example:
-
- class ConstantVisitor(NodeVisitor):
- def __init__(self):
- self.values = []
-
- def visit_Constant(self, node):
- self.values.append(node.value)
-
- Creates a list of values of all the constant nodes
- encountered below the given node. To use it:
-
- cv = ConstantVisitor()
- cv.visit(node)
-
- Notes:
-
- * generic_visit() will be called for AST nodes for which
- no visit_XXX method was defined.
- * The children of nodes for which a visit_XXX was
- defined will not be visited - if you need this, call
- generic_visit() on the node.
- You can use:
- NodeVisitor.generic_visit(self, node)
- * Modeled after Python's own AST visiting facilities
- (the ast module of Python 3.0)
- """
- def visit(self, node):
- """ Visit a node.
- """
- method = 'visit_' + node.__class__.__name__
- visitor = getattr(self, method, self.generic_visit)
- return visitor(node)
-
- def generic_visit(self, node):
- """ Called if no explicit visitor function exists for a
- node. Implements preorder visiting of the node.
- """
- for c in node.children():
- self.visit(c)
-
-
-'''
-
-
-
-if __name__ == "__main__":
- import sys
-
- ast_gen = ASTCodeGenerator('_c_ast.yaml')
- ast_gen.generate(open('c_ast.py', 'w'))
-
-
-
+ src = ' def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):\n'
+ src += " lead = ' ' * offset\n"
+
+ src += " buf.write(lead + '%s: ')\n\n" % self.name
+
+ if self.attr:
+ src += " if attrnames:\n"
+ src += " attrstr = ', '.join('%s=%s' % nv for nv in ["
+ src += ', '.join('("%s", repr(%s))' % (nv, 'self.%s' % nv) for nv in self.attr)
+ src += '])\n'
+ src += " else:\n"
+ src += " attrstr = ', '.join('%s' % v for v in ["
+ src += ', '.join('self.%s' % v for v in self.attr)
+ src += '])\n'
+ src += " buf.write(attrstr)\n\n"
+
+ src += " if showcoord:\n"
+ src += " buf.write(' (at %s)' % self.coord)\n"
+ src += " buf.write('\\n')\n\n"
+
+ src += " for c in self.children():\n"
+ src += " c.show(buf, offset + 2, attrnames, showcoord)\n"
+
+ return src
+
+
+_PROLOGUE_COMMENT = \
+r'''#-----------------------------------------------------------------
+# ** ATTENTION **
+# This code was automatically generated from the file:
+# $cfg_filename
+#
+# Do not modify it directly. Modify the configuration file and
+# run the generator again.
+# ** ** *** ** **
+#
+# pycparser: c_ast.py
+#
+# AST Node classes.
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+'''
+
+_PROLOGUE_CODE = r'''
+import sys
+
+
+class Node(object):
+ """ Abstract base class for AST nodes.
+ """
+ def children(self):
+ """ A sequence of all children that are Nodes
+ """
+ pass
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ """ Pretty print the Node and all its attributes and
+ children (recursively) to a buffer.
+
+ file:
+ Open IO buffer into which the Node is printed.
+
+ offset:
+ Initial offset (amount of leading spaces)
+
+ attrnames:
+ True if you want to see the attribute names in
+ name=value pairs. False to only see the values.
+
+ showcoord:
+ Do you want the coordinates of each Node to be
+ displayed.
+ """
+ pass
+
+
+class NodeVisitor(object):
+ """ A base NodeVisitor class for visiting c_ast nodes.
+ Subclass it and define your own visit_XXX methods, where
+ XXX is the class name you want to visit with these
+ methods.
+
+ For example:
+
+ class ConstantVisitor(NodeVisitor):
+ def __init__(self):
+ self.values = []
+
+ def visit_Constant(self, node):
+ self.values.append(node.value)
+
+ Creates a list of values of all the constant nodes
+ encountered below the given node. To use it:
+
+ cv = ConstantVisitor()
+ cv.visit(node)
+
+ Notes:
+
+ * generic_visit() will be called for AST nodes for which
+ no visit_XXX method was defined.
+ * The children of nodes for which a visit_XXX was
+ defined will not be visited - if you need this, call
+ generic_visit() on the node.
+ You can use:
+ NodeVisitor.generic_visit(self, node)
+ * Modeled after Python's own AST visiting facilities
+ (the ast module of Python 3.0)
+ """
+ def visit(self, node):
+ """ Visit a node.
+ """
+ method = 'visit_' + node.__class__.__name__
+ visitor = getattr(self, method, self.generic_visit)
+ return visitor(node)
+
+ def generic_visit(self, node):
+ """ Called if no explicit visitor function exists for a
+ node. Implements preorder visiting of the node.
+ """
+ for c in node.children():
+ self.visit(c)
+
+
+'''
+
+
+if __name__ == "__main__":
+ import sys
+ ast_gen = ASTCodeGenerator('_c_ast.cfg')
+ ast_gen.generate(open('c_ast.py', 'w'))
+
diff --git a/pycparser/_build_tables.py b/pycparser/_build_tables.py
index 902773e..04524e0 100644
--- a/pycparser/_build_tables.py
+++ b/pycparser/_build_tables.py
@@ -3,7 +3,8 @@
#
# A dummy for generating the lexing/parsing tables and and
# compiling them into .pyc for faster execution in optimized mode.
-# Also generates AST code from the _c_ast.yaml configuration file.
+# Also generates AST code from the configuration file.
+# Should be called from the installation directory.
#
# Copyright (C) 2008-2010, Eli Bendersky
# License: LGPL
@@ -12,7 +13,7 @@
# Generate c_ast.py
#
from _ast_gen import ASTCodeGenerator
-ast_gen = ASTCodeGenerator('_c_ast.yaml')
+ast_gen = ASTCodeGenerator('_c_ast.cfg')
ast_gen.generate(open('c_ast.py', 'w'))
from pycparser import c_parser
diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py
index 12d690c..532fa8e 100644
--- a/pycparser/c_ast.py
+++ b/pycparser/c_ast.py
@@ -1,1237 +1,1237 @@
-#-----------------------------------------------------------------
-# ** ATTENTION **
-# This code was automatically generated from the file:
-# _c_ast.yaml
-#
-# Do not modify it directly. Modify the configuration file and
-# run the generator again.
-# ** ** *** ** **
-#
-# pycparser: c_ast.py
-#
-# AST Node classes.
-#
-# Copyright (C) 2008, Eli Bendersky
-# License: LGPL
-#-----------------------------------------------------------------
-
-
-import sys
-
-
-class Node(object):
- """ Abstract base class for AST nodes.
- """
- def children(self):
- """ A sequence of all children that are Nodes
- """
- pass
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- """ Pretty print the Node and all its attributes and
- children (recursively) to a buffer.
-
- file:
- Open IO buffer into which the Node is printed.
-
- offset:
- Initial offset (amount of leading spaces)
-
- attrnames:
- True if you want to see the attribute names in
- name=value pairs. False to only see the values.
-
- showcoord:
- Do you want the coordinates of each Node to be
- displayed.
- """
- pass
-
-
-class NodeVisitor(object):
- """ A base NodeVisitor class for visiting c_ast nodes.
- Subclass it and define your own visit_XXX methods, where
- XXX is the class name you want to visit with these
- methods.
-
- For example:
-
- class ConstantVisitor(NodeVisitor):
- def __init__(self):
- self.values = []
-
- def visit_Constant(self, node):
- self.values.append(node.value)
-
- Creates a list of values of all the constant nodes
- encountered below the given node. To use it:
-
- cv = ConstantVisitor()
- cv.visit(node)
-
- Notes:
-
- * generic_visit() will be called for AST nodes for which
- no visit_XXX method was defined.
- * The children of nodes for which a visit_XXX was
- defined will not be visited - if you need this, call
- generic_visit() on the node.
- You can use:
- NodeVisitor.generic_visit(self, node)
- * Modeled after Python's own AST visiting facilities
- (the ast module of Python 3.0)
- """
- def visit(self, node):
- """ Visit a node.
- """
- method = 'visit_' + node.__class__.__name__
- visitor = getattr(self, method, self.generic_visit)
- return visitor(node)
-
- def generic_visit(self, node):
- """ Called if no explicit visitor function exists for a
- node. Implements preorder visiting of the node.
- """
- for c in node.children():
- self.visit(c)
-
-
-class Typedef(Node):
- def __init__(self, name, quals, storage, type, coord=None):
- self.name = name
- self.quals = quals
- self.storage = storage
- self.type = type
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Typedef: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Struct(Node):
- def __init__(self, name, decls, coord=None):
- self.name = name
- self.decls = decls
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.decls is not None: nodelist.extend(self.decls)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Struct: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class For(Node):
- def __init__(self, init, cond, next, stmt, coord=None):
- self.init = init
- self.cond = cond
- self.next = next
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.init is not None: nodelist.append(self.init)
- if self.cond is not None: nodelist.append(self.cond)
- if self.next is not None: nodelist.append(self.next)
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'For: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class UnaryOp(Node):
- def __init__(self, op, expr, coord=None):
- self.op = op
- self.expr = expr
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.expr is not None: nodelist.append(self.expr)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'UnaryOp: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.op])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Union(Node):
- def __init__(self, name, decls, coord=None):
- self.name = name
- self.decls = decls
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.decls is not None: nodelist.extend(self.decls)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Union: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class CompoundLiteral(Node):
- def __init__(self, type, init, coord=None):
- self.type = type
- self.init = init
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- if self.init is not None: nodelist.append(self.init)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'CompoundLiteral: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class TernaryOp(Node):
- def __init__(self, cond, iftrue, iffalse, coord=None):
- self.cond = cond
- self.iftrue = iftrue
- self.iffalse = iffalse
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.cond is not None: nodelist.append(self.cond)
- if self.iftrue is not None: nodelist.append(self.iftrue)
- if self.iffalse is not None: nodelist.append(self.iffalse)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'TernaryOp: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Label(Node):
- def __init__(self, name, stmt, coord=None):
- self.name = name
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Label: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class IdentifierType(Node):
- def __init__(self, names, coord=None):
- self.names = names
- self.coord = coord
-
- def children(self):
- nodelist = []
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'IdentifierType: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("names", repr(self.names))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.names])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class FuncDef(Node):
- def __init__(self, decl, param_decls, body, coord=None):
- self.decl = decl
- self.param_decls = param_decls
- self.body = body
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.decl is not None: nodelist.append(self.decl)
- if self.body is not None: nodelist.append(self.body)
- if self.param_decls is not None: nodelist.extend(self.param_decls)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'FuncDef: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class DeclList(Node):
- def __init__(self, decls, coord=None):
- self.decls = decls
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.decls is not None: nodelist.extend(self.decls)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'DeclList: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Enumerator(Node):
- def __init__(self, name, value, coord=None):
- self.name = name
- self.value = value
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.value is not None: nodelist.append(self.value)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Enumerator: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class FuncCall(Node):
- def __init__(self, name, args, coord=None):
- self.name = name
- self.args = args
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.name is not None: nodelist.append(self.name)
- if self.args is not None: nodelist.append(self.args)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'FuncCall: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Assignment(Node):
- def __init__(self, op, lvalue, rvalue, coord=None):
- self.op = op
- self.lvalue = lvalue
- self.rvalue = rvalue
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.lvalue is not None: nodelist.append(self.lvalue)
- if self.rvalue is not None: nodelist.append(self.rvalue)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Assignment: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.op])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class FuncDecl(Node):
- def __init__(self, args, type, coord=None):
- self.args = args
- self.type = type
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.args is not None: nodelist.append(self.args)
- if self.type is not None: nodelist.append(self.type)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'FuncDecl: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Enum(Node):
- def __init__(self, name, values, coord=None):
- self.name = name
- self.values = values
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.values is not None: nodelist.append(self.values)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Enum: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class ExprList(Node):
- def __init__(self, exprs, coord=None):
- self.exprs = exprs
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.exprs is not None: nodelist.extend(self.exprs)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'ExprList: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Break(Node):
- def __init__(self, coord=None):
- self.coord = coord
-
- def children(self):
- return ()
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Break: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class DoWhile(Node):
- def __init__(self, cond, stmt, coord=None):
- self.cond = cond
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.cond is not None: nodelist.append(self.cond)
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'DoWhile: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class StructRef(Node):
- def __init__(self, name, type, field, coord=None):
- self.name = name
- self.type = type
- self.field = field
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.name is not None: nodelist.append(self.name)
- if self.field is not None: nodelist.append(self.field)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'StructRef: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.type])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class BinaryOp(Node):
- def __init__(self, op, left, right, coord=None):
- self.op = op
- self.left = left
- self.right = right
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.left is not None: nodelist.append(self.left)
- if self.right is not None: nodelist.append(self.right)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'BinaryOp: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.op])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Compound(Node):
- def __init__(self, block_items, coord=None):
- self.block_items = block_items
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.block_items is not None: nodelist.extend(self.block_items)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Compound: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class ArrayDecl(Node):
- def __init__(self, type, dim, coord=None):
- self.type = type
- self.dim = dim
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- if self.dim is not None: nodelist.append(self.dim)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'ArrayDecl: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Case(Node):
- def __init__(self, expr, stmt, coord=None):
- self.expr = expr
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.expr is not None: nodelist.append(self.expr)
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Case: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Cast(Node):
- def __init__(self, to_type, expr, coord=None):
- self.to_type = to_type
- self.expr = expr
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.to_type is not None: nodelist.append(self.to_type)
- if self.expr is not None: nodelist.append(self.expr)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Cast: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class TypeDecl(Node):
- def __init__(self, declname, quals, type, coord=None):
- self.declname = declname
- self.quals = quals
- self.type = type
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'TypeDecl: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("declname", repr(self.declname)), ("quals", repr(self.quals))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.declname, self.quals])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Default(Node):
- def __init__(self, stmt, coord=None):
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Default: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class PtrDecl(Node):
- def __init__(self, quals, type, coord=None):
- self.quals = quals
- self.type = type
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'PtrDecl: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.quals])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Switch(Node):
- def __init__(self, cond, stmt, coord=None):
- self.cond = cond
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.cond is not None: nodelist.append(self.cond)
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Switch: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Continue(Node):
- def __init__(self, coord=None):
- self.coord = coord
-
- def children(self):
- return ()
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Continue: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class ParamList(Node):
- def __init__(self, params, coord=None):
- self.params = params
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.params is not None: nodelist.extend(self.params)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'ParamList: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Return(Node):
- def __init__(self, expr, coord=None):
- self.expr = expr
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.expr is not None: nodelist.append(self.expr)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Return: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Typename(Node):
- def __init__(self, quals, type, coord=None):
- self.quals = quals
- self.type = type
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Typename: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.quals])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class ID(Node):
- def __init__(self, name, coord=None):
- self.name = name
- self.coord = coord
-
- def children(self):
- nodelist = []
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'ID: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Goto(Node):
- def __init__(self, name, coord=None):
- self.name = name
- self.coord = coord
-
- def children(self):
- nodelist = []
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Goto: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Decl(Node):
- def __init__(self, name, quals, storage, funcspec, type, init, bitsize, coord=None):
- self.name = name
- self.quals = quals
- self.storage = storage
- self.funcspec = funcspec
- self.type = type
- self.init = init
- self.bitsize = bitsize
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.type is not None: nodelist.append(self.type)
- if self.init is not None: nodelist.append(self.init)
- if self.bitsize is not None: nodelist.append(self.bitsize)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Decl: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage)), ("funcspec", repr(self.funcspec))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage, self.funcspec])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class Constant(Node):
- def __init__(self, type, value, coord=None):
- self.type = type
- self.value = value
- self.coord = coord
-
- def children(self):
- nodelist = []
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'Constant: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type)), ("value", repr(self.value))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.type, self.value])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class FileAST(Node):
- def __init__(self, ext, coord=None):
- self.ext = ext
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.ext is not None: nodelist.extend(self.ext)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'FileAST: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class ArrayRef(Node):
- def __init__(self, name, subscript, coord=None):
- self.name = name
- self.subscript = subscript
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.name is not None: nodelist.append(self.name)
- if self.subscript is not None: nodelist.append(self.subscript)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'ArrayRef: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class While(Node):
- def __init__(self, cond, stmt, coord=None):
- self.cond = cond
- self.stmt = stmt
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.cond is not None: nodelist.append(self.cond)
- if self.stmt is not None: nodelist.append(self.stmt)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'While: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class NamedInitializer(Node):
- def __init__(self, name, expr, coord=None):
- self.name = name
- self.expr = expr
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.expr is not None: nodelist.append(self.expr)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'NamedInitializer: ')
-
- if attrnames:
- attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
- else:
- attrstr = ', '.join('%s' % v for v in [self.name])
- buf.write(attrstr)
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class EnumeratorList(Node):
- def __init__(self, enumerators, coord=None):
- self.enumerators = enumerators
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.enumerators is not None: nodelist.extend(self.enumerators)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'EnumeratorList: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class EllipsisParam(Node):
- def __init__(self, coord=None):
- self.coord = coord
-
- def children(self):
- return ()
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'EllipsisParam: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
-class If(Node):
- def __init__(self, cond, iftrue, iffalse, coord=None):
- self.cond = cond
- self.iftrue = iftrue
- self.iffalse = iffalse
- self.coord = coord
-
- def children(self):
- nodelist = []
- if self.cond is not None: nodelist.append(self.cond)
- if self.iftrue is not None: nodelist.append(self.iftrue)
- if self.iffalse is not None: nodelist.append(self.iffalse)
- return tuple(nodelist)
-
- def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
- lead = ' ' * offset
- buf.write(lead + 'If: ')
-
- if showcoord:
- buf.write(' (at %s)' % self.coord)
- buf.write('\n')
-
- for c in self.children():
- c.show(buf, offset + 2, attrnames, showcoord)
-
-
+#-----------------------------------------------------------------
+# ** ATTENTION **
+# This code was automatically generated from the file:
+# _c_ast.cfg
+#
+# Do not modify it directly. Modify the configuration file and
+# run the generator again.
+# ** ** *** ** **
+#
+# pycparser: c_ast.py
+#
+# AST Node classes.
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+
+import sys
+
+
+class Node(object):
+ """ Abstract base class for AST nodes.
+ """
+ def children(self):
+ """ A sequence of all children that are Nodes
+ """
+ pass
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ """ Pretty print the Node and all its attributes and
+ children (recursively) to a buffer.
+
+ file:
+ Open IO buffer into which the Node is printed.
+
+ offset:
+ Initial offset (amount of leading spaces)
+
+ attrnames:
+ True if you want to see the attribute names in
+ name=value pairs. False to only see the values.
+
+ showcoord:
+ Do you want the coordinates of each Node to be
+ displayed.
+ """
+ pass
+
+
+class NodeVisitor(object):
+ """ A base NodeVisitor class for visiting c_ast nodes.
+ Subclass it and define your own visit_XXX methods, where
+ XXX is the class name you want to visit with these
+ methods.
+
+ For example:
+
+ class ConstantVisitor(NodeVisitor):
+ def __init__(self):
+ self.values = []
+
+ def visit_Constant(self, node):
+ self.values.append(node.value)
+
+ Creates a list of values of all the constant nodes
+ encountered below the given node. To use it:
+
+ cv = ConstantVisitor()
+ cv.visit(node)
+
+ Notes:
+
+ * generic_visit() will be called for AST nodes for which
+ no visit_XXX method was defined.
+ * The children of nodes for which a visit_XXX was
+ defined will not be visited - if you need this, call
+ generic_visit() on the node.
+ You can use:
+ NodeVisitor.generic_visit(self, node)
+ * Modeled after Python's own AST visiting facilities
+ (the ast module of Python 3.0)
+ """
+ def visit(self, node):
+ """ Visit a node.
+ """
+ method = 'visit_' + node.__class__.__name__
+ visitor = getattr(self, method, self.generic_visit)
+ return visitor(node)
+
+ def generic_visit(self, node):
+ """ Called if no explicit visitor function exists for a
+ node. Implements preorder visiting of the node.
+ """
+ for c in node.children():
+ self.visit(c)
+
+
+class ArrayDecl(Node):
+ def __init__(self, type, dim, coord=None):
+ self.type = type
+ self.dim = dim
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ if self.dim is not None: nodelist.append(self.dim)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'ArrayDecl: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ArrayRef(Node):
+ def __init__(self, name, subscript, coord=None):
+ self.name = name
+ self.subscript = subscript
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.name is not None: nodelist.append(self.name)
+ if self.subscript is not None: nodelist.append(self.subscript)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'ArrayRef: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Assignment(Node):
+ def __init__(self, op, lvalue, rvalue, coord=None):
+ self.op = op
+ self.lvalue = lvalue
+ self.rvalue = rvalue
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.lvalue is not None: nodelist.append(self.lvalue)
+ if self.rvalue is not None: nodelist.append(self.rvalue)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Assignment: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.op])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class BinaryOp(Node):
+ def __init__(self, op, left, right, coord=None):
+ self.op = op
+ self.left = left
+ self.right = right
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.left is not None: nodelist.append(self.left)
+ if self.right is not None: nodelist.append(self.right)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'BinaryOp: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.op])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Break(Node):
+ def __init__(self, coord=None):
+ self.coord = coord
+
+ def children(self):
+ return ()
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Break: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Case(Node):
+ def __init__(self, expr, stmt, coord=None):
+ self.expr = expr
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.expr is not None: nodelist.append(self.expr)
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Case: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Cast(Node):
+ def __init__(self, to_type, expr, coord=None):
+ self.to_type = to_type
+ self.expr = expr
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.to_type is not None: nodelist.append(self.to_type)
+ if self.expr is not None: nodelist.append(self.expr)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Cast: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Compound(Node):
+ def __init__(self, block_items, coord=None):
+ self.block_items = block_items
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.block_items is not None: nodelist.extend(self.block_items)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Compound: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class CompoundLiteral(Node):
+ def __init__(self, type, init, coord=None):
+ self.type = type
+ self.init = init
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ if self.init is not None: nodelist.append(self.init)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'CompoundLiteral: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Constant(Node):
+ def __init__(self, type, value, coord=None):
+ self.type = type
+ self.value = value
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Constant: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type)), ("value", repr(self.value))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.type, self.value])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Continue(Node):
+ def __init__(self, coord=None):
+ self.coord = coord
+
+ def children(self):
+ return ()
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Continue: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Decl(Node):
+ def __init__(self, name, quals, storage, funcspec, type, init, bitsize, coord=None):
+ self.name = name
+ self.quals = quals
+ self.storage = storage
+ self.funcspec = funcspec
+ self.type = type
+ self.init = init
+ self.bitsize = bitsize
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ if self.init is not None: nodelist.append(self.init)
+ if self.bitsize is not None: nodelist.append(self.bitsize)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Decl: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage)), ("funcspec", repr(self.funcspec))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage, self.funcspec])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class DeclList(Node):
+ def __init__(self, decls, coord=None):
+ self.decls = decls
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.decls is not None: nodelist.extend(self.decls)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'DeclList: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Default(Node):
+ def __init__(self, stmt, coord=None):
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Default: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class DoWhile(Node):
+ def __init__(self, cond, stmt, coord=None):
+ self.cond = cond
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.cond is not None: nodelist.append(self.cond)
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'DoWhile: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class EllipsisParam(Node):
+ def __init__(self, coord=None):
+ self.coord = coord
+
+ def children(self):
+ return ()
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'EllipsisParam: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Enum(Node):
+ def __init__(self, name, values, coord=None):
+ self.name = name
+ self.values = values
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.values is not None: nodelist.append(self.values)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Enum: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Enumerator(Node):
+ def __init__(self, name, value, coord=None):
+ self.name = name
+ self.value = value
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.value is not None: nodelist.append(self.value)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Enumerator: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class EnumeratorList(Node):
+ def __init__(self, enumerators, coord=None):
+ self.enumerators = enumerators
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.enumerators is not None: nodelist.extend(self.enumerators)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'EnumeratorList: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ExprList(Node):
+ def __init__(self, exprs, coord=None):
+ self.exprs = exprs
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.exprs is not None: nodelist.extend(self.exprs)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'ExprList: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FileAST(Node):
+ def __init__(self, ext, coord=None):
+ self.ext = ext
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.ext is not None: nodelist.extend(self.ext)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'FileAST: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class For(Node):
+ def __init__(self, init, cond, next, stmt, coord=None):
+ self.init = init
+ self.cond = cond
+ self.next = next
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.init is not None: nodelist.append(self.init)
+ if self.cond is not None: nodelist.append(self.cond)
+ if self.next is not None: nodelist.append(self.next)
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'For: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FuncCall(Node):
+ def __init__(self, name, args, coord=None):
+ self.name = name
+ self.args = args
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.name is not None: nodelist.append(self.name)
+ if self.args is not None: nodelist.append(self.args)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'FuncCall: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FuncDecl(Node):
+ def __init__(self, args, type, coord=None):
+ self.args = args
+ self.type = type
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.args is not None: nodelist.append(self.args)
+ if self.type is not None: nodelist.append(self.type)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'FuncDecl: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FuncDef(Node):
+ def __init__(self, decl, param_decls, body, coord=None):
+ self.decl = decl
+ self.param_decls = param_decls
+ self.body = body
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.decl is not None: nodelist.append(self.decl)
+ if self.body is not None: nodelist.append(self.body)
+ if self.param_decls is not None: nodelist.extend(self.param_decls)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'FuncDef: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Goto(Node):
+ def __init__(self, name, coord=None):
+ self.name = name
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Goto: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ID(Node):
+ def __init__(self, name, coord=None):
+ self.name = name
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'ID: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class IdentifierType(Node):
+ def __init__(self, names, coord=None):
+ self.names = names
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'IdentifierType: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("names", repr(self.names))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.names])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class If(Node):
+ def __init__(self, cond, iftrue, iffalse, coord=None):
+ self.cond = cond
+ self.iftrue = iftrue
+ self.iffalse = iffalse
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.cond is not None: nodelist.append(self.cond)
+ if self.iftrue is not None: nodelist.append(self.iftrue)
+ if self.iffalse is not None: nodelist.append(self.iffalse)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'If: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Label(Node):
+ def __init__(self, name, stmt, coord=None):
+ self.name = name
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Label: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class NamedInitializer(Node):
+ def __init__(self, name, expr, coord=None):
+ self.name = name
+ self.expr = expr
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.expr is not None: nodelist.append(self.expr)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'NamedInitializer: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ParamList(Node):
+ def __init__(self, params, coord=None):
+ self.params = params
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.params is not None: nodelist.extend(self.params)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'ParamList: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class PtrDecl(Node):
+ def __init__(self, quals, type, coord=None):
+ self.quals = quals
+ self.type = type
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'PtrDecl: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.quals])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Return(Node):
+ def __init__(self, expr, coord=None):
+ self.expr = expr
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.expr is not None: nodelist.append(self.expr)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Return: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Struct(Node):
+ def __init__(self, name, decls, coord=None):
+ self.name = name
+ self.decls = decls
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.decls is not None: nodelist.extend(self.decls)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Struct: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class StructRef(Node):
+ def __init__(self, name, type, field, coord=None):
+ self.name = name
+ self.type = type
+ self.field = field
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.name is not None: nodelist.append(self.name)
+ if self.field is not None: nodelist.append(self.field)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'StructRef: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.type])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Switch(Node):
+ def __init__(self, cond, stmt, coord=None):
+ self.cond = cond
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.cond is not None: nodelist.append(self.cond)
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Switch: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class TernaryOp(Node):
+ def __init__(self, cond, iftrue, iffalse, coord=None):
+ self.cond = cond
+ self.iftrue = iftrue
+ self.iffalse = iffalse
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.cond is not None: nodelist.append(self.cond)
+ if self.iftrue is not None: nodelist.append(self.iftrue)
+ if self.iffalse is not None: nodelist.append(self.iffalse)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'TernaryOp: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class TypeDecl(Node):
+ def __init__(self, declname, quals, type, coord=None):
+ self.declname = declname
+ self.quals = quals
+ self.type = type
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'TypeDecl: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("declname", repr(self.declname)), ("quals", repr(self.quals))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.declname, self.quals])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Typedef(Node):
+ def __init__(self, name, quals, storage, type, coord=None):
+ self.name = name
+ self.quals = quals
+ self.storage = storage
+ self.type = type
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Typedef: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Typename(Node):
+ def __init__(self, quals, type, coord=None):
+ self.quals = quals
+ self.type = type
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.type is not None: nodelist.append(self.type)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Typename: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.quals])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class UnaryOp(Node):
+ def __init__(self, op, expr, coord=None):
+ self.op = op
+ self.expr = expr
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.expr is not None: nodelist.append(self.expr)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'UnaryOp: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.op])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Union(Node):
+ def __init__(self, name, decls, coord=None):
+ self.name = name
+ self.decls = decls
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.decls is not None: nodelist.extend(self.decls)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'Union: ')
+
+ if attrnames:
+ attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+ else:
+ attrstr = ', '.join('%s' % v for v in [self.name])
+ buf.write(attrstr)
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class While(Node):
+ def __init__(self, cond, stmt, coord=None):
+ self.cond = cond
+ self.stmt = stmt
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.cond is not None: nodelist.append(self.cond)
+ if self.stmt is not None: nodelist.append(self.stmt)
+ return tuple(nodelist)
+
+ def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+ lead = ' ' * offset
+ buf.write(lead + 'While: ')
+
+ if showcoord:
+ buf.write(' (at %s)' % self.coord)
+ buf.write('\n')
+
+ for c in self.children():
+ c.show(buf, offset + 2, attrnames, showcoord)
+
+
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index e9d0403..38c80b3 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -1,1354 +1,1353 @@
-#-----------------------------------------------------------------
-# pycparser: c_parser.py
-#
-# CParser class: Parser and AST builder for the C language
-#
-# Copyright (C) 2008-2010, Eli Bendersky
-# License: LGPL
-#-----------------------------------------------------------------
-
-import re
-
-import ply.yacc
-
-from . import c_ast
-from .c_lexer import CLexer
-from .plyparser import PLYParser, Coord, ParseError
-
-
-class CParser(PLYParser):
- def __init__(
- self,
- lex_optimize=True,
- lextab='pycparser.lextab',
- yacc_optimize=True,
- yacctab='pycparser.yacctab',
- yacc_debug=False):
- """ Create a new CParser.
-
- Some arguments for controlling the debug/optimization
- level of the parser are provided. The defaults are
- tuned for release/performance mode.
- The simple rules for using them are:
- *) When tweaking CParser/CLexer, set these to False
- *) When releasing a stable parser, set to True
-
- lex_optimize:
- Set to False when you're modifying the lexer.
- Otherwise, changes in the lexer won't be used, if
- some lextab.py file exists.
- When releasing with a stable lexer, set to True
- to save the re-generation of the lexer table on
- each run.
-
- lextab:
- Points to the lex table that's used for optimized
- mode. Only if you're modifying the lexer and want
- some tests to avoid re-generating the table, make
- this point to a local lex table file (that's been
- earlier generated with lex_optimize=True)
-
- yacc_optimize:
- Set to False when you're modifying the parser.
- Otherwise, changes in the parser won't be used, if
- some parsetab.py file exists.
- When releasing with a stable parser, set to True
- to save the re-generation of the parser table on
- each run.
-
- yacctab:
- Points to the yacc table that's used for optimized
- mode. Only if you're modifying the parser, make
- this point to a local yacc table file
-
- yacc_debug:
- Generate a parser.out file that explains how yacc
- built the parsing table from the grammar.
- """
- self.clex = CLexer(
- error_func=self._lex_error_func,
- type_lookup_func=self._lex_type_lookup_func)
-
- self.clex.build(
- optimize=lex_optimize,
- lextab=lextab)
- self.tokens = self.clex.tokens
-
- rules_with_opt = [
- 'abstract_declarator',
- 'assignment_expression',
- 'declaration_list',
- 'declaration_specifiers',
- 'designation',
- 'expression',
- 'identifier_list',
- 'init_declarator_list',
- 'parameter_type_list',
- 'specifier_qualifier_list',
- 'block_item_list',
- 'type_qualifier_list',
- ]
-
- for rule in rules_with_opt:
- self._create_opt_rule(rule)
-
- self.cparser = ply.yacc.yacc(
- module=self,
- start='translation_unit',
- debug=yacc_debug,
- optimize=yacc_optimize,
- tabmodule=yacctab)
-
- # A table of identifiers defined as typedef types during
- # parsing.
- #
- self.typedef_table = set([])
-
- def parse(self, text, filename='', debuglevel=0):
- """ Parses C code and returns an AST.
-
- text:
- A string containing the C source code
-
- filename:
- Name of the file being parsed (for meaningful
- error messages)
-
- debuglevel:
- Debug level to yacc
- """
- self.clex.filename = filename
- self.clex.reset_lineno()
- self.typedef_table = set([])
- return self.cparser.parse(text, lexer=self.clex, debug=debuglevel)
-
- ######################-- PRIVATE --######################
-
- def _lex_error_func(self, msg, line, column):
- self._parse_error(msg, self._coord(line, column))
-
- def _lex_type_lookup_func(self, name):
- """ Looks up types that were previously defined with
- typedef.
- Passed to the lexer for recognizing identifiers that
- are types.
- """
- return name in self.typedef_table
-
- def _add_typedef_type(self, name):
- """ Adds names that were defined as new types with
- typedef.
- """
- self.typedef_table.add(name)
-
- # To understand what's going on here, read sections A.8.5 and
- # A.8.6 of K&R2 very carefully.
- #
- # A C type consists of a basic type declaration, with a list
- # of modifiers. For example:
- #
- # int *c[5];
- #
- # The basic declaration here is 'int x', and the pointer and
- # the array are the modifiers.
- #
- # Basic declarations are represented by TypeDecl (from module
- # c_ast) and the modifiers are FuncDecl, PtrDecl and
- # ArrayDecl.
- #
- # The standard states that whenever a new modifier is parsed,
- # it should be added to the end of the list of modifiers. For
- # example:
- #
- # K&R2 A.8.6.2: Array Declarators
- #
- # In a declaration T D where D has the form
- # D1 [constant-expression-opt]
- # and the type of the identifier in the declaration T D1 is
- # "type-modifier T", the type of the
- # identifier of D is "type-modifier array of T"
- #
- # This is what this method does. The declarator it receives
- # can be a list of declarators ending with TypeDecl. It
- # tacks the modifier to the end of this list, just before
- # the TypeDecl.
- #
- # Additionally, the modifier may be a list itself. This is
- # useful for pointers, that can come as a chain from the rule
- # p_pointer. In this case, the whole modifier list is spliced
- # into the new location.
- #
- def _type_modify_decl(self, decl, modifier):
- """ Tacks a type modifier on a declarator, and returns
- the modified declarator.
-
- Note: the declarator and modifier may be modified
- """
- #~ print '****'
- #~ decl.show(offset=3)
- #~ modifier.show(offset=3)
- #~ print '****'
-
- modifier_head = modifier
- modifier_tail = modifier
-
- # The modifier may be a nested list. Reach its tail.
- #
- while modifier_tail.type:
- modifier_tail = modifier_tail.type
-
- # If the decl is a basic type, just tack the modifier onto
- # it
- #
- if isinstance(decl, c_ast.TypeDecl):
- modifier_tail.type = decl
- return modifier
- else:
- # Otherwise, the decl is a list of modifiers. Reach
- # its tail and splice the modifier onto the tail,
- # pointing to the underlying basic type.
- #
- decl_tail = decl
-
- while not isinstance(decl_tail.type, c_ast.TypeDecl):
- decl_tail = decl_tail.type
-
- modifier_tail.type = decl_tail.type
- decl_tail.type = modifier_head
- return decl
-
- # Due to the order in which declarators are constructed,
- # they have to be fixed in order to look like a normal AST.
- #
- # When a declaration arrives from syntax construction, it has
- # these problems:
- # * The innermost TypeDecl has no type (because the basic
- # type is only known at the uppermost declaration level)
- # * The declaration has no variable name, since that is saved
- # in the innermost TypeDecl
- # * The typename of the declaration is a list of type
- # specifiers, and not a node. Here, basic identifier types
- # should be separated from more complex types like enums
- # and structs.
- #
- # This method fixes these problem.
- #
- def _fix_decl_name_type(self, decl, typename):
- """ Fixes a declaration. Modifies decl.
- """
- # Reach the underlying basic type
- #
- type = decl
- while not isinstance(type, c_ast.TypeDecl):
- type = type.type
-
- decl.name = type.declname
- type.quals = decl.quals
-
- # The typename is a list of types. If any type in this
- # list isn't a simple string type, it must be the only
- # type in the list (it's illegal to declare "int enum .."
- # If all the types are basic, they're collected in the
- # IdentifierType holder.
- #
- for tn in typename:
- if not isinstance(tn, str):
- if len(typename) > 1:
- self._parse_error(
- "Invalid multiple types specified", tn.coord)
- else:
- type.type = tn
- return decl
-
- type.type = c_ast.IdentifierType(typename)
- return decl
-
- def _add_declaration_specifier(self, declspec, newspec, kind):
- """ Declaration specifiers are represented by a dictionary
- with the entries:
- * qual: a list of type qualifiers
- * storage: a list of storage type qualifiers
- * type: a list of type specifiers
- * function: a list of function specifiers
-
- This method is given a declaration specifier, and a
- new specifier of a given kind.
- Returns the declaration specifier, with the new
- specifier incorporated.
- """
- spec = declspec or dict(qual=[], storage=[], type=[], function=[])
- spec[kind].append(newspec)
- return spec
-
- def _build_function_definition(self, decl, spec, param_decls, body):
- """ Builds a function definition.
- """
- declaration = c_ast.Decl(
- name=None,
- quals=spec['qual'],
- storage=spec['storage'],
- funcspec=spec['function'],
- type=decl,
- init=None,
- bitsize=None,
- coord=decl.coord)
-
- typename = spec['type']
- declaration = self._fix_decl_name_type(declaration, typename)
- return c_ast.FuncDef(
- decl=declaration,
- param_decls=param_decls,
- body=body,
- coord=decl.coord)
-
- def _select_struct_union_class(self, token):
- """ Given a token (either STRUCT or UNION), selects the
- appropriate AST class.
- """
- if token == 'struct':
- return c_ast.Struct
- else:
- return c_ast.Union
-
- ##
- ## Precedence and associativity of operators
- ##
- precedence = (
- ('left', 'LOR'),
- ('left', 'LAND'),
- ('left', 'OR'),
- ('left', 'XOR'),
- ('left', 'AND'),
- ('left', 'EQ', 'NE'),
- ('left', 'GT', 'GE', 'LT', 'LE'),
- ('left', 'RSHIFT', 'LSHIFT'),
- ('left', 'PLUS', 'MINUS'),
- ('left', 'TIMES', 'DIVIDE', 'MOD')
- )
-
- ##
- ## Grammar productions
- ## Implementation of the BNF defined in K&R2 A.13
- ##
- def p_translation_unit_1(self, p):
- """ translation_unit : external_declaration
- """
- # Note: external_declaration is already a list
- #
- p[0] = c_ast.FileAST(p[1])
-
- def p_translation_unit_2(self, p):
- """ translation_unit : translation_unit external_declaration
- """
- p[1].ext.extend(p[2])
- p[0] = p[1]
-
- # Declarations always come as lists (because they can be
- # several in one line), so we wrap the function definition
- # into a list as well, to make the return value of
- # external_declaration homogenous.
- #
- def p_external_declaration_1(self, p):
- """ external_declaration : function_definition
- """
- p[0] = [p[1]]
-
- def p_external_declaration_2(self, p):
- """ external_declaration : declaration
- """
- p[0] = p[1]
-
- def p_external_declaration_3(self, p):
- """ external_declaration : pp_directive
- """
- p[0] = p[1]
-
- def p_pp_directive(self, p):
- """ pp_directive : PPHASH
- """
- self._parse_error('Directives not supported yet',
- self._coord(p.lineno(1)))
-
- # In function definitions, the declarator can be followed by
- # a declaration list, for old "K&R style" function definitios.
- #
- def p_function_definition_1(self, p):
- """ function_definition : declarator declaration_list_opt compound_statement
- """
- # no declaration specifiers
- spec = dict(qual=[], storage=[], type=[])
-
- p[0] = self._build_function_definition(
- decl=p[1],
- spec=spec,
- param_decls=p[2],
- body=p[3])
-
- def p_function_definition_2(self, p):
- """ function_definition : declaration_specifiers declarator declaration_list_opt compound_statement
- """
- spec = p[1]
-
- p[0] = self._build_function_definition(
- decl=p[2],
- spec=spec,
- param_decls=p[3],
- body=p[4])
-
- def p_statement(self, p):
- """ statement : labeled_statement
- | expression_statement
- | compound_statement
- | selection_statement
- | iteration_statement
- | jump_statement
- """
- p[0] = p[1]
-
- # In C, declarations can come several in a line:
- # int x, *px, romulo = 5;
- #
- # However, for the AST, we will split them to separate Decl
- # nodes.
- #
- # This rule splits its declarations and always returns a list
- # of Decl nodes, even if it's one element long.
- #
- def p_decl_body(self, p):
- """ decl_body : declaration_specifiers init_declarator_list_opt
- """
- spec = p[1]
- is_typedef = 'typedef' in spec['storage']
- decls = []
-
- # p[2] (init_declarator_list_opt) is either a list or None
- #
- if p[2] is None:
- # Then it's a declaration of a struct / enum tag,
- # without an actual declarator.
- #
- type = spec['type']
- if len(type) > 1:
- coord = '?'
- for t in type:
- if hasattr(t, 'coord'):
- coord = t.coord
- break
-
- self._parse_error('Multiple type specifiers with a type tag', coord)
-
- decl = c_ast.Decl(
- name=None,
- quals=spec['qual'],
- storage=spec['storage'],
- funcspec=spec['function'],
- type=type[0],
- init=None,
- bitsize=None,
- coord=type[0].coord)
- decls = [decl]
- else:
- for decl, init in p[2] or []:
- if is_typedef:
- decl = c_ast.Typedef(
- name=None,
- quals=spec['qual'],
- storage=spec['storage'],
- type=decl,
- coord=decl.coord)
- else:
- decl = c_ast.Decl(
- name=None,
- quals=spec['qual'],
- storage=spec['storage'],
- funcspec=spec['function'],
- type=decl,
- init=init,
- bitsize=None,
- coord=decl.coord)
-
- typename = spec['type']
- fixed_decl = self._fix_decl_name_type(decl, typename)
-
- # Add the type name defined by typedef to a
- # symbol table (for usage in the lexer)
- #
- if is_typedef:
- self._add_typedef_type(fixed_decl.name)
-
- decls.append(fixed_decl)
-
- p[0] = decls
-
- # The declaration has been split to a decl_body sub-rule and
- # SEMI, because having them in a single rule created a problem
- # for defining typedefs.
- #
- # If a typedef line was directly followed by a line using the
- # type defined with the typedef, the type would not be
- # recognized. This is because to reduce the declaration rule,
- # the parser's lookahead asked for the token after SEMI, which
- # was the type from the next line, and the lexer had no chance
- # to see the updated type symbol table.
- #
- # Splitting solves this problem, because after seeing SEMI,
- # the parser reduces decl_body, which actually adds the new
- # type into the table to be seen by the lexer before the next
- # line is reached.
- #
- def p_declaration(self, p):
- """ declaration : decl_body SEMI
- """
- p[0] = p[1]
-
- # Since each declaration is a list of declarations, this
- # rule will combine all the declarations and return a single
- # list
- #
- def p_declaration_list(self, p):
- """ declaration_list : declaration
- | declaration_list declaration
- """
- p[0] = p[1] if len(p) == 2 else p[1] + p[2]
-
- def p_declaration_specifiers_1(self, p):
- """ declaration_specifiers : type_qualifier declaration_specifiers_opt
- """
- p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')
-
- def p_declaration_specifiers_2(self, p):
- """ declaration_specifiers : type_specifier declaration_specifiers_opt
- """
- p[0] = self._add_declaration_specifier(p[2], p[1], 'type')
-
- def p_declaration_specifiers_3(self, p):
- """ declaration_specifiers : storage_class_specifier declaration_specifiers_opt
- """
- p[0] = self._add_declaration_specifier(p[2], p[1], 'storage')
-
- def p_declaration_specifiers_4(self, p):
- """ declaration_specifiers : function_specifier declaration_specifiers_opt
- """
- p[0] = self._add_declaration_specifier(p[2], p[1], 'function')
-
- def p_storage_class_specifier(self, p):
- """ storage_class_specifier : AUTO
- | REGISTER
- | STATIC
- | EXTERN
- | TYPEDEF
- """
- p[0] = p[1]
-
+#-----------------------------------------------------------------
+# pycparser: c_parser.py
+#
+# CParser class: Parser and AST builder for the C language
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+import re
+
+import ply.yacc
+
+from . import c_ast
+from .c_lexer import CLexer
+from .plyparser import PLYParser, Coord, ParseError
+
+
+class CParser(PLYParser):
+ def __init__(
+ self,
+ lex_optimize=True,
+ lextab='pycparser.lextab',
+ yacc_optimize=True,
+ yacctab='pycparser.yacctab',
+ yacc_debug=False):
+ """ Create a new CParser.
+
+ Some arguments for controlling the debug/optimization
+ level of the parser are provided. The defaults are
+ tuned for release/performance mode.
+ The simple rules for using them are:
+ *) When tweaking CParser/CLexer, set these to False
+ *) When releasing a stable parser, set to True
+
+ lex_optimize:
+ Set to False when you're modifying the lexer.
+ Otherwise, changes in the lexer won't be used, if
+ some lextab.py file exists.
+ When releasing with a stable lexer, set to True
+ to save the re-generation of the lexer table on
+ each run.
+
+ lextab:
+ Points to the lex table that's used for optimized
+ mode. Only if you're modifying the lexer and want
+ some tests to avoid re-generating the table, make
+ this point to a local lex table file (that's been
+ earlier generated with lex_optimize=True)
+
+ yacc_optimize:
+ Set to False when you're modifying the parser.
+ Otherwise, changes in the parser won't be used, if
+ some parsetab.py file exists.
+ When releasing with a stable parser, set to True
+ to save the re-generation of the parser table on
+ each run.
+
+ yacctab:
+ Points to the yacc table that's used for optimized
+ mode. Only if you're modifying the parser, make
+ this point to a local yacc table file
+
+ yacc_debug:
+ Generate a parser.out file that explains how yacc
+ built the parsing table from the grammar.
+ """
+ self.clex = CLexer(
+ error_func=self._lex_error_func,
+ type_lookup_func=self._lex_type_lookup_func)
+
+ self.clex.build(
+ optimize=lex_optimize,
+ lextab=lextab)
+ self.tokens = self.clex.tokens
+
+ rules_with_opt = [
+ 'abstract_declarator',
+ 'assignment_expression',
+ 'declaration_list',
+ 'declaration_specifiers',
+ 'designation',
+ 'expression',
+ 'identifier_list',
+ 'init_declarator_list',
+ 'parameter_type_list',
+ 'specifier_qualifier_list',
+ 'block_item_list',
+ 'type_qualifier_list',
+ ]
+
+ for rule in rules_with_opt:
+ self._create_opt_rule(rule)
+
+ self.cparser = ply.yacc.yacc(
+ module=self,
+ start='translation_unit',
+ debug=yacc_debug,
+ optimize=yacc_optimize,
+ tabmodule=yacctab)
+
+ # A table of identifiers defined as typedef types during
+ # parsing.
+ #
+ self.typedef_table = set([])
+
+ def parse(self, text, filename='', debuglevel=0):
+ """ Parses C code and returns an AST.
+
+ text:
+ A string containing the C source code
+
+ filename:
+ Name of the file being parsed (for meaningful
+ error messages)
+
+ debuglevel:
+ Debug level to yacc
+ """
+ self.clex.filename = filename
+ self.clex.reset_lineno()
+ self.typedef_table = set([])
+ return self.cparser.parse(text, lexer=self.clex, debug=debuglevel)
+
+ ######################-- PRIVATE --######################
+
+ def _lex_error_func(self, msg, line, column):
+ self._parse_error(msg, self._coord(line, column))
+
+ def _lex_type_lookup_func(self, name):
+ """ Looks up types that were previously defined with
+ typedef.
+ Passed to the lexer for recognizing identifiers that
+ are types.
+ """
+ return name in self.typedef_table
+
+ def _add_typedef_type(self, name):
+ """ Adds names that were defined as new types with
+ typedef.
+ """
+ self.typedef_table.add(name)
+
+ # To understand what's going on here, read sections A.8.5 and
+ # A.8.6 of K&R2 very carefully.
+ #
+ # A C type consists of a basic type declaration, with a list
+ # of modifiers. For example:
+ #
+ # int *c[5];
+ #
+ # The basic declaration here is 'int x', and the pointer and
+ # the array are the modifiers.
+ #
+ # Basic declarations are represented by TypeDecl (from module
+ # c_ast) and the modifiers are FuncDecl, PtrDecl and
+ # ArrayDecl.
+ #
+ # The standard states that whenever a new modifier is parsed,
+ # it should be added to the end of the list of modifiers. For
+ # example:
+ #
+ # K&R2 A.8.6.2: Array Declarators
+ #
+ # In a declaration T D where D has the form
+ # D1 [constant-expression-opt]
+ # and the type of the identifier in the declaration T D1 is
+ # "type-modifier T", the type of the
+ # identifier of D is "type-modifier array of T"
+ #
+ # This is what this method does. The declarator it receives
+ # can be a list of declarators ending with TypeDecl. It
+ # tacks the modifier to the end of this list, just before
+ # the TypeDecl.
+ #
+ # Additionally, the modifier may be a list itself. This is
+ # useful for pointers, that can come as a chain from the rule
+ # p_pointer. In this case, the whole modifier list is spliced
+ # into the new location.
+ #
+ def _type_modify_decl(self, decl, modifier):
+ """ Tacks a type modifier on a declarator, and returns
+ the modified declarator.
+
+ Note: the declarator and modifier may be modified
+ """
+ #~ print '****'
+ #~ decl.show(offset=3)
+ #~ modifier.show(offset=3)
+ #~ print '****'
+
+ modifier_head = modifier
+ modifier_tail = modifier
+
+ # The modifier may be a nested list. Reach its tail.
+ #
+ while modifier_tail.type:
+ modifier_tail = modifier_tail.type
+
+ # If the decl is a basic type, just tack the modifier onto
+ # it
+ #
+ if isinstance(decl, c_ast.TypeDecl):
+ modifier_tail.type = decl
+ return modifier
+ else:
+ # Otherwise, the decl is a list of modifiers. Reach
+ # its tail and splice the modifier onto the tail,
+ # pointing to the underlying basic type.
+ #
+ decl_tail = decl
+
+ while not isinstance(decl_tail.type, c_ast.TypeDecl):
+ decl_tail = decl_tail.type
+
+ modifier_tail.type = decl_tail.type
+ decl_tail.type = modifier_head
+ return decl
+
+ # Due to the order in which declarators are constructed,
+ # they have to be fixed in order to look like a normal AST.
+ #
+ # When a declaration arrives from syntax construction, it has
+ # these problems:
+ # * The innermost TypeDecl has no type (because the basic
+ # type is only known at the uppermost declaration level)
+ # * The declaration has no variable name, since that is saved
+ # in the innermost TypeDecl
+ # * The typename of the declaration is a list of type
+ # specifiers, and not a node. Here, basic identifier types
+ # should be separated from more complex types like enums
+ # and structs.
+ #
+ # This method fixes these problem.
+ #
+ def _fix_decl_name_type(self, decl, typename):
+ """ Fixes a declaration. Modifies decl.
+ """
+ # Reach the underlying basic type
+ #
+ type = decl
+ while not isinstance(type, c_ast.TypeDecl):
+ type = type.type
+
+ decl.name = type.declname
+ type.quals = decl.quals
+
+ # The typename is a list of types. If any type in this
+ # list isn't a simple string type, it must be the only
+ # type in the list (it's illegal to declare "int enum .."
+ # If all the types are basic, they're collected in the
+ # IdentifierType holder.
+ #
+ for tn in typename:
+ if not isinstance(tn, str):
+ if len(typename) > 1:
+ self._parse_error(
+ "Invalid multiple types specified", tn.coord)
+ else:
+ type.type = tn
+ return decl
+
+ type.type = c_ast.IdentifierType(typename)
+ return decl
+
+ def _add_declaration_specifier(self, declspec, newspec, kind):
+ """ Declaration specifiers are represented by a dictionary
+ with the entries:
+ * qual: a list of type qualifiers
+ * storage: a list of storage type qualifiers
+ * type: a list of type specifiers
+ * function: a list of function specifiers
+
+ This method is given a declaration specifier, and a
+ new specifier of a given kind.
+ Returns the declaration specifier, with the new
+ specifier incorporated.
+ """
+ spec = declspec or dict(qual=[], storage=[], type=[], function=[])
+ spec[kind].append(newspec)
+ return spec
+
+ def _build_function_definition(self, decl, spec, param_decls, body):
+ """ Builds a function definition.
+ """
+ declaration = c_ast.Decl(
+ name=None,
+ quals=spec['qual'],
+ storage=spec['storage'],
+ funcspec=spec['function'],
+ type=decl,
+ init=None,
+ bitsize=None,
+ coord=decl.coord)
+
+ typename = spec['type']
+ declaration = self._fix_decl_name_type(declaration, typename)
+ return c_ast.FuncDef(
+ decl=declaration,
+ param_decls=param_decls,
+ body=body,
+ coord=decl.coord)
+
+ def _select_struct_union_class(self, token):
+ """ Given a token (either STRUCT or UNION), selects the
+ appropriate AST class.
+ """
+ if token == 'struct':
+ return c_ast.Struct
+ else:
+ return c_ast.Union
+
+ ##
+ ## Precedence and associativity of operators
+ ##
+ precedence = (
+ ('left', 'LOR'),
+ ('left', 'LAND'),
+ ('left', 'OR'),
+ ('left', 'XOR'),
+ ('left', 'AND'),
+ ('left', 'EQ', 'NE'),
+ ('left', 'GT', 'GE', 'LT', 'LE'),
+ ('left', 'RSHIFT', 'LSHIFT'),
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE', 'MOD')
+ )
+
+ ##
+ ## Grammar productions
+ ## Implementation of the BNF defined in K&R2 A.13
+ ##
+ def p_translation_unit_1(self, p):
+ """ translation_unit : external_declaration
+ """
+ # Note: external_declaration is already a list
+ #
+ p[0] = c_ast.FileAST(p[1])
+
+ def p_translation_unit_2(self, p):
+ """ translation_unit : translation_unit external_declaration
+ """
+ p[1].ext.extend(p[2])
+ p[0] = p[1]
+
+ # Declarations always come as lists (because they can be
+ # several in one line), so we wrap the function definition
+ # into a list as well, to make the return value of
+ # external_declaration homogenous.
+ #
+ def p_external_declaration_1(self, p):
+ """ external_declaration : function_definition
+ """
+ p[0] = [p[1]]
+
+ def p_external_declaration_2(self, p):
+ """ external_declaration : declaration
+ """
+ p[0] = p[1]
+
+ def p_external_declaration_3(self, p):
+ """ external_declaration : pp_directive
+ """
+ p[0] = p[1]
+
+ def p_pp_directive(self, p):
+ """ pp_directive : PPHASH
+ """
+ self._parse_error('Directives not supported yet',
+ self._coord(p.lineno(1)))
+
+ # In function definitions, the declarator can be followed by
+ # a declaration list, for old "K&R style" function definitios.
+ #
+ def p_function_definition_1(self, p):
+ """ function_definition : declarator declaration_list_opt compound_statement
+ """
+ # no declaration specifiers
+ spec = dict(qual=[], storage=[], type=[])
+
+ p[0] = self._build_function_definition(
+ decl=p[1],
+ spec=spec,
+ param_decls=p[2],
+ body=p[3])
+
+ def p_function_definition_2(self, p):
+ """ function_definition : declaration_specifiers declarator declaration_list_opt compound_statement
+ """
+ spec = p[1]
+
+ p[0] = self._build_function_definition(
+ decl=p[2],
+ spec=spec,
+ param_decls=p[3],
+ body=p[4])
+
+ def p_statement(self, p):
+ """ statement : labeled_statement
+ | expression_statement
+ | compound_statement
+ | selection_statement
+ | iteration_statement
+ | jump_statement
+ """
+ p[0] = p[1]
+
+ # In C, declarations can come several in a line:
+ # int x, *px, romulo = 5;
+ #
+ # However, for the AST, we will split them to separate Decl
+ # nodes.
+ #
+ # This rule splits its declarations and always returns a list
+ # of Decl nodes, even if it's one element long.
+ #
+ def p_decl_body(self, p):
+ """ decl_body : declaration_specifiers init_declarator_list_opt
+ """
+ spec = p[1]
+ is_typedef = 'typedef' in spec['storage']
+ decls = []
+
+ # p[2] (init_declarator_list_opt) is either a list or None
+ #
+ if p[2] is None:
+ # Then it's a declaration of a struct / enum tag,
+ # without an actual declarator.
+ #
+ type = spec['type']
+ if len(type) > 1:
+ coord = '?'
+ for t in type:
+ if hasattr(t, 'coord'):
+ coord = t.coord
+ break
+
+ self._parse_error('Multiple type specifiers with a type tag', coord)
+
+ decl = c_ast.Decl(
+ name=None,
+ quals=spec['qual'],
+ storage=spec['storage'],
+ funcspec=spec['function'],
+ type=type[0],
+ init=None,
+ bitsize=None,
+ coord=type[0].coord)
+ decls = [decl]
+ else:
+ for decl, init in p[2] or []:
+ if is_typedef:
+ decl = c_ast.Typedef(
+ name=None,
+ quals=spec['qual'],
+ storage=spec['storage'],
+ type=decl,
+ coord=decl.coord)
+ else:
+ decl = c_ast.Decl(
+ name=None,
+ quals=spec['qual'],
+ storage=spec['storage'],
+ funcspec=spec['function'],
+ type=decl,
+ init=init,
+ bitsize=None,
+ coord=decl.coord)
+
+ typename = spec['type']
+ fixed_decl = self._fix_decl_name_type(decl, typename)
+
+ # Add the type name defined by typedef to a
+ # symbol table (for usage in the lexer)
+ #
+ if is_typedef:
+ self._add_typedef_type(fixed_decl.name)
+
+ decls.append(fixed_decl)
+
+ p[0] = decls
+
+ # The declaration has been split to a decl_body sub-rule and
+ # SEMI, because having them in a single rule created a problem
+ # for defining typedefs.
+ #
+ # If a typedef line was directly followed by a line using the
+ # type defined with the typedef, the type would not be
+ # recognized. This is because to reduce the declaration rule,
+ # the parser's lookahead asked for the token after SEMI, which
+ # was the type from the next line, and the lexer had no chance
+ # to see the updated type symbol table.
+ #
+ # Splitting solves this problem, because after seeing SEMI,
+ # the parser reduces decl_body, which actually adds the new
+ # type into the table to be seen by the lexer before the next
+ # line is reached.
+ #
+ def p_declaration(self, p):
+ """ declaration : decl_body SEMI
+ """
+ p[0] = p[1]
+
+ # Since each declaration is a list of declarations, this
+ # rule will combine all the declarations and return a single
+ # list
+ #
+ def p_declaration_list(self, p):
+ """ declaration_list : declaration
+ | declaration_list declaration
+ """
+ p[0] = p[1] if len(p) == 2 else p[1] + p[2]
+
+ def p_declaration_specifiers_1(self, p):
+ """ declaration_specifiers : type_qualifier declaration_specifiers_opt
+ """
+ p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')
+
+ def p_declaration_specifiers_2(self, p):
+ """ declaration_specifiers : type_specifier declaration_specifiers_opt
+ """
+ p[0] = self._add_declaration_specifier(p[2], p[1], 'type')
+
+ def p_declaration_specifiers_3(self, p):
+ """ declaration_specifiers : storage_class_specifier declaration_specifiers_opt
+ """
+ p[0] = self._add_declaration_specifier(p[2], p[1], 'storage')
+
+ def p_declaration_specifiers_4(self, p):
+ """ declaration_specifiers : function_specifier declaration_specifiers_opt
+ """
+ p[0] = self._add_declaration_specifier(p[2], p[1], 'function')
+
+ def p_storage_class_specifier(self, p):
+ """ storage_class_specifier : AUTO
+ | REGISTER
+ | STATIC
+ | EXTERN
+ | TYPEDEF
+ """
+ p[0] = p[1]
+
def p_function_specifier(self, p):
""" function_specifier : INLINE
- """
- p[0] = p[1]
-
- def p_type_specifier_1(self, p):
- """ type_specifier : VOID
- | CHAR
- | SHORT
- | INT
- | LONG
- | FLOAT
- | DOUBLE
- | SIGNED
- | UNSIGNED
- | typedef_name
- | enum_specifier
- | struct_or_union_specifier
- """
- p[0] = p[1]
-
- def p_type_qualifier(self, p):
- """ type_qualifier : CONST
- | RESTRICT
- | VOLATILE
- """
- p[0] = p[1]
-
- def p_init_declarator_list(self, p):
- """ init_declarator_list : init_declarator
- | init_declarator_list COMMA init_declarator
- """
- p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]
-
- # Returns a (declarator, initializer) pair
- # If there's no initializer, returns (declarator, None)
- #
- def p_init_declarator(self, p):
- """ init_declarator : declarator
- | declarator EQUALS initializer
- """
- p[0] = (p[1], p[3] if len(p) > 2 else None)
-
- def p_specifier_qualifier_list_1(self, p):
- """ specifier_qualifier_list : type_qualifier specifier_qualifier_list_opt
- """
- p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')
-
- def p_specifier_qualifier_list_2(self, p):
- """ specifier_qualifier_list : type_specifier specifier_qualifier_list_opt
- """
- p[0] = self._add_declaration_specifier(p[2], p[1], 'type')
-
- # TYPEID is allowed here (and in other struct/enum related tag names), because
- # struct/enum tags reside in their own namespace and can be named the same as types
- #
- def p_struct_or_union_specifier_1(self, p):
- """ struct_or_union_specifier : struct_or_union ID
- | struct_or_union TYPEID
- """
- klass = self._select_struct_union_class(p[1])
- p[0] = klass(
- name=p[2],
- decls=None,
- coord=self._coord(p.lineno(2)))
-
- def p_struct_or_union_specifier_2(self, p):
- """ struct_or_union_specifier : struct_or_union LBRACE struct_declaration_list RBRACE
- """
- klass = self._select_struct_union_class(p[1])
- p[0] = klass(
- name=None,
- decls=p[3],
- coord=self._coord(p.lineno(2)))
-
- def p_struct_or_union_specifier_3(self, p):
- """ struct_or_union_specifier : struct_or_union ID LBRACE struct_declaration_list RBRACE
- | struct_or_union TYPEID LBRACE struct_declaration_list RBRACE
- """
- klass = self._select_struct_union_class(p[1])
- p[0] = klass(
- name=p[2],
- decls=p[4],
- coord=self._coord(p.lineno(2)))
-
- def p_struct_or_union(self, p):
- """ struct_or_union : STRUCT
- | UNION
- """
- p[0] = p[1]
-
- # Combine all declarations into a single list
- #
- def p_struct_declaration_list(self, p):
- """ struct_declaration_list : struct_declaration
- | struct_declaration_list struct_declaration
- """
- p[0] = p[1] if len(p) == 2 else p[1] + p[2]
-
- def p_struct_declaration_1(self, p):
- """ struct_declaration : specifier_qualifier_list struct_declarator_list SEMI
- """
- spec = p[1]
- decls = []
-
- for struct_decl in p[2]:
- if struct_decl['decl'] is not None:
- decl_coord = struct_decl['decl'].coord
- else:
- decl_coord = struct_decl['bitsize'].coord
-
- decl = c_ast.Decl(
- name=None,
- quals=spec['qual'],
- funcspec=spec['function'],
- storage=spec['storage'],
- type=struct_decl['decl'],
- init=None,
- bitsize=struct_decl['bitsize'],
- coord=decl_coord)
-
- typename = spec['type']
- decls.append(self._fix_decl_name_type(decl, typename))
-
- p[0] = decls
-
- def p_struct_declarator_list(self, p):
- """ struct_declarator_list : struct_declarator
- | struct_declarator_list COMMA struct_declarator
- """
- p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]
-
- # struct_declarator passes up a dict with the keys: decl (for
- # the underlying declarator) and bitsize (for the bitsize)
- #
- def p_struct_declarator_1(self, p):
- """ struct_declarator : declarator
- """
- p[0] = {'decl': p[1], 'bitsize': None}
-
- def p_struct_declarator_2(self, p):
- """ struct_declarator : declarator COLON constant_expression
- | COLON constant_expression
- """
- if len(p) > 3:
- p[0] = {'decl': p[1], 'bitsize': p[3]}
- else:
- p[0] = {'decl': c_ast.TypeDecl(None, None, None), 'bitsize': p[2]}
-
- def p_enum_specifier_1(self, p):
- """ enum_specifier : ENUM ID
- | ENUM TYPEID
- """
- p[0] = c_ast.Enum(p[2], None, self._coord(p.lineno(1)))
-
- def p_enum_specifier_2(self, p):
- """ enum_specifier : ENUM LBRACE enumerator_list RBRACE
- """
- p[0] = c_ast.Enum(None, p[3], self._coord(p.lineno(1)))
-
- def p_enum_specifier_3(self, p):
- """ enum_specifier : ENUM ID LBRACE enumerator_list RBRACE
- | ENUM TYPEID LBRACE enumerator_list RBRACE
- """
- p[0] = c_ast.Enum(p[2], p[4], self._coord(p.lineno(1)))
-
- def p_enumerator_list(self, p):
- """ enumerator_list : enumerator
- | enumerator_list COMMA
- | enumerator_list COMMA enumerator
- """
- if len(p) == 2:
- p[0] = c_ast.EnumeratorList([p[1]], p[1].coord)
- elif len(p) == 3:
- p[0] = p[1]
- else:
- p[1].enumerators.append(p[3])
- p[0] = p[1]
-
- def p_enumerator(self, p):
- """ enumerator : ID
- | ID EQUALS constant_expression
- """
- if len(p) == 2:
- p[0] = c_ast.Enumerator(
- p[1], None,
- self._coord(p.lineno(1)))
- else:
- p[0] = c_ast.Enumerator(
- p[1], p[3],
- self._coord(p.lineno(1)))
-
- def p_declarator_1(self, p):
- """ declarator : direct_declarator
- """
- p[0] = p[1]
-
- def p_declarator_2(self, p):
- """ declarator : pointer direct_declarator
- """
- p[0] = self._type_modify_decl(p[2], p[1])
-
- def p_direct_declarator_1(self, p):
- """ direct_declarator : ID
- """
- p[0] = c_ast.TypeDecl(
- declname=p[1],
- type=None,
- quals=None,
- coord=self._coord(p.lineno(1)))
-
- def p_direct_declarator_2(self, p):
- """ direct_declarator : LPAREN declarator RPAREN
- """
- p[0] = p[2]
-
- def p_direct_declarator_3(self, p):
- """ direct_declarator : direct_declarator LBRACKET assignment_expression_opt RBRACKET
- """
- arr = c_ast.ArrayDecl(
- type=None,
- dim=p[3],
- coord=p[1].coord)
-
- p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
-
- # Special for VLAs
- #
- def p_direct_declarator_4(self, p):
- """ direct_declarator : direct_declarator LBRACKET TIMES RBRACKET
- """
- arr = c_ast.ArrayDecl(
- type=None,
- dim=c_ast.ID(p[3], self._coord(p.lineno(3))),
- coord=p[1].coord)
-
- p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
-
- def p_direct_declarator_5(self, p):
- """ direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN
- | direct_declarator LPAREN identifier_list_opt RPAREN
- """
- func = c_ast.FuncDecl(
- args=p[3],
- type=None,
- coord=p[1].coord)
-
- p[0] = self._type_modify_decl(decl=p[1], modifier=func)
-
- def p_pointer(self, p):
- """ pointer : TIMES type_qualifier_list_opt
- | TIMES type_qualifier_list_opt pointer
- """
- coord = self._coord(p.lineno(1))
-
- p[0] = c_ast.PtrDecl(
- quals=p[2] or [],
- type=p[3] if len(p) > 3 else None,
- coord=coord)
-
- def p_type_qualifier_list(self, p):
- """ type_qualifier_list : type_qualifier
- | type_qualifier_list type_qualifier
- """
- p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]]
-
- def p_parameter_type_list(self, p):
- """ parameter_type_list : parameter_list
- | parameter_list COMMA ELLIPSIS
- """
- if len(p) > 2:
- p[1].params.append(c_ast.EllipsisParam())
-
- p[0] = p[1]
-
- def p_parameter_list(self, p):
- """ parameter_list : parameter_declaration
- | parameter_list COMMA parameter_declaration
- """
- if len(p) == 2: # single parameter
- p[0] = c_ast.ParamList([p[1]], p[1].coord)
- else:
- p[1].params.append(p[3])
- p[0] = p[1]
-
- def p_parameter_declaration_1(self, p):
- """ parameter_declaration : declaration_specifiers declarator
- """
- spec = p[1]
- decl = p[2]
-
- decl = c_ast.Decl(
- name=None,
- quals=spec['qual'],
- storage=spec['storage'],
- funcspec=spec['function'],
- type=decl,
- init=None,
- bitsize=None,
- coord=decl.coord)
-
- typename = spec['type'] or ['int']
- p[0] = self._fix_decl_name_type(decl, typename)
-
- def p_parameter_declaration_2(self, p):
- """ parameter_declaration : declaration_specifiers abstract_declarator_opt
- """
- spec = p[1]
- decl = c_ast.Typename(
- quals=spec['qual'],
- type=p[2] or c_ast.TypeDecl(None, None, None))
-
- typename = spec['type'] or ['int']
- p[0] = self._fix_decl_name_type(decl, typename)
-
- def p_identifier_list(self, p):
- """ identifier_list : identifier
- | identifier_list COMMA identifier
- """
- if len(p) == 2: # single parameter
- p[0] = c_ast.ParamList([p[1]], p[1].coord)
- else:
- p[1].params.append(p[3])
- p[0] = p[1]
-
- def p_initializer_1(self, p):
- """ initializer : assignment_expression
- """
- p[0] = p[1]
-
- def p_initializer_2(self, p):
- """ initializer : LBRACE initializer_list RBRACE
- | LBRACE initializer_list COMMA RBRACE
- """
- p[0] = p[2]
-
- def p_initializer_list(self, p):
- """ initializer_list : designation_opt initializer
- | initializer_list COMMA designation_opt initializer
- """
- if len(p) == 3: # single initializer
- init = p[2] if p[1] is None else c_ast.NamedInitializer(p[1], p[2])
- p[0] = c_ast.ExprList([init], p[2].coord)
- else:
- init = p[4] if p[3] is None else c_ast.NamedInitializer(p[3], p[4])
- p[1].exprs.append(init)
- p[0] = p[1]
-
+ """
+ p[0] = p[1]
+
+ def p_type_specifier_1(self, p):
+ """ type_specifier : VOID
+ | CHAR
+ | SHORT
+ | INT
+ | LONG
+ | FLOAT
+ | DOUBLE
+ | SIGNED
+ | UNSIGNED
+ | typedef_name
+ | enum_specifier
+ | struct_or_union_specifier
+ """
+ p[0] = p[1]
+
+ def p_type_qualifier(self, p):
+ """ type_qualifier : CONST
+ | RESTRICT
+ | VOLATILE
+ """
+ p[0] = p[1]
+
+ def p_init_declarator_list(self, p):
+ """ init_declarator_list : init_declarator
+ | init_declarator_list COMMA init_declarator
+ """
+ p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]
+
+ # Returns a (declarator, initializer) pair
+ # If there's no initializer, returns (declarator, None)
+ #
+ def p_init_declarator(self, p):
+ """ init_declarator : declarator
+ | declarator EQUALS initializer
+ """
+ p[0] = (p[1], p[3] if len(p) > 2 else None)
+
+ def p_specifier_qualifier_list_1(self, p):
+ """ specifier_qualifier_list : type_qualifier specifier_qualifier_list_opt
+ """
+ p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')
+
+ def p_specifier_qualifier_list_2(self, p):
+ """ specifier_qualifier_list : type_specifier specifier_qualifier_list_opt
+ """
+ p[0] = self._add_declaration_specifier(p[2], p[1], 'type')
+
+ # TYPEID is allowed here (and in other struct/enum related tag names), because
+ # struct/enum tags reside in their own namespace and can be named the same as types
+ #
+ def p_struct_or_union_specifier_1(self, p):
+ """ struct_or_union_specifier : struct_or_union ID
+ | struct_or_union TYPEID
+ """
+ klass = self._select_struct_union_class(p[1])
+ p[0] = klass(
+ name=p[2],
+ decls=None,
+ coord=self._coord(p.lineno(2)))
+
+ def p_struct_or_union_specifier_2(self, p):
+ """ struct_or_union_specifier : struct_or_union LBRACE struct_declaration_list RBRACE
+ """
+ klass = self._select_struct_union_class(p[1])
+ p[0] = klass(
+ name=None,
+ decls=p[3],
+ coord=self._coord(p.lineno(2)))
+
+ def p_struct_or_union_specifier_3(self, p):
+ """ struct_or_union_specifier : struct_or_union ID LBRACE struct_declaration_list RBRACE
+ | struct_or_union TYPEID LBRACE struct_declaration_list RBRACE
+ """
+ klass = self._select_struct_union_class(p[1])
+ p[0] = klass(
+ name=p[2],
+ decls=p[4],
+ coord=self._coord(p.lineno(2)))
+
+ def p_struct_or_union(self, p):
+ """ struct_or_union : STRUCT
+ | UNION
+ """
+ p[0] = p[1]
+
+ # Combine all declarations into a single list
+ #
+ def p_struct_declaration_list(self, p):
+ """ struct_declaration_list : struct_declaration
+ | struct_declaration_list struct_declaration
+ """
+ p[0] = p[1] if len(p) == 2 else p[1] + p[2]
+
+ def p_struct_declaration_1(self, p):
+ """ struct_declaration : specifier_qualifier_list struct_declarator_list SEMI
+ """
+ spec = p[1]
+ decls = []
+
+ for struct_decl in p[2]:
+ if struct_decl['decl'] is not None:
+ decl_coord = struct_decl['decl'].coord
+ else:
+ decl_coord = struct_decl['bitsize'].coord
+
+ decl = c_ast.Decl(
+ name=None,
+ quals=spec['qual'],
+ funcspec=spec['function'],
+ storage=spec['storage'],
+ type=struct_decl['decl'],
+ init=None,
+ bitsize=struct_decl['bitsize'],
+ coord=decl_coord)
+
+ typename = spec['type']
+ decls.append(self._fix_decl_name_type(decl, typename))
+
+ p[0] = decls
+
+ def p_struct_declarator_list(self, p):
+ """ struct_declarator_list : struct_declarator
+ | struct_declarator_list COMMA struct_declarator
+ """
+ p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]
+
+ # struct_declarator passes up a dict with the keys: decl (for
+ # the underlying declarator) and bitsize (for the bitsize)
+ #
+ def p_struct_declarator_1(self, p):
+ """ struct_declarator : declarator
+ """
+ p[0] = {'decl': p[1], 'bitsize': None}
+
+ def p_struct_declarator_2(self, p):
+ """ struct_declarator : declarator COLON constant_expression
+ | COLON constant_expression
+ """
+ if len(p) > 3:
+ p[0] = {'decl': p[1], 'bitsize': p[3]}
+ else:
+ p[0] = {'decl': c_ast.TypeDecl(None, None, None), 'bitsize': p[2]}
+
+ def p_enum_specifier_1(self, p):
+ """ enum_specifier : ENUM ID
+ | ENUM TYPEID
+ """
+ p[0] = c_ast.Enum(p[2], None, self._coord(p.lineno(1)))
+
+ def p_enum_specifier_2(self, p):
+ """ enum_specifier : ENUM LBRACE enumerator_list RBRACE
+ """
+ p[0] = c_ast.Enum(None, p[3], self._coord(p.lineno(1)))
+
+ def p_enum_specifier_3(self, p):
+ """ enum_specifier : ENUM ID LBRACE enumerator_list RBRACE
+ | ENUM TYPEID LBRACE enumerator_list RBRACE
+ """
+ p[0] = c_ast.Enum(p[2], p[4], self._coord(p.lineno(1)))
+
+ def p_enumerator_list(self, p):
+ """ enumerator_list : enumerator
+ | enumerator_list COMMA
+ | enumerator_list COMMA enumerator
+ """
+ if len(p) == 2:
+ p[0] = c_ast.EnumeratorList([p[1]], p[1].coord)
+ elif len(p) == 3:
+ p[0] = p[1]
+ else:
+ p[1].enumerators.append(p[3])
+ p[0] = p[1]
+
+ def p_enumerator(self, p):
+ """ enumerator : ID
+ | ID EQUALS constant_expression
+ """
+ if len(p) == 2:
+ p[0] = c_ast.Enumerator(
+ p[1], None,
+ self._coord(p.lineno(1)))
+ else:
+ p[0] = c_ast.Enumerator(
+ p[1], p[3],
+ self._coord(p.lineno(1)))
+
+ def p_declarator_1(self, p):
+ """ declarator : direct_declarator
+ """
+ p[0] = p[1]
+
+ def p_declarator_2(self, p):
+ """ declarator : pointer direct_declarator
+ """
+ p[0] = self._type_modify_decl(p[2], p[1])
+
+ def p_direct_declarator_1(self, p):
+ """ direct_declarator : ID
+ """
+ p[0] = c_ast.TypeDecl(
+ declname=p[1],
+ type=None,
+ quals=None,
+ coord=self._coord(p.lineno(1)))
+
+ def p_direct_declarator_2(self, p):
+ """ direct_declarator : LPAREN declarator RPAREN
+ """
+ p[0] = p[2]
+
+ def p_direct_declarator_3(self, p):
+ """ direct_declarator : direct_declarator LBRACKET assignment_expression_opt RBRACKET
+ """
+ arr = c_ast.ArrayDecl(
+ type=None,
+ dim=p[3],
+ coord=p[1].coord)
+
+ p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
+
+ # Special for VLAs
+ #
+ def p_direct_declarator_4(self, p):
+ """ direct_declarator : direct_declarator LBRACKET TIMES RBRACKET
+ """
+ arr = c_ast.ArrayDecl(
+ type=None,
+ dim=c_ast.ID(p[3], self._coord(p.lineno(3))),
+ coord=p[1].coord)
+
+ p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
+
+ def p_direct_declarator_5(self, p):
+ """ direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN
+ | direct_declarator LPAREN identifier_list_opt RPAREN
+ """
+ func = c_ast.FuncDecl(
+ args=p[3],
+ type=None,
+ coord=p[1].coord)
+
+ p[0] = self._type_modify_decl(decl=p[1], modifier=func)
+
+ def p_pointer(self, p):
+ """ pointer : TIMES type_qualifier_list_opt
+ | TIMES type_qualifier_list_opt pointer
+ """
+ coord = self._coord(p.lineno(1))
+
+ p[0] = c_ast.PtrDecl(
+ quals=p[2] or [],
+ type=p[3] if len(p) > 3 else None,
+ coord=coord)
+
+ def p_type_qualifier_list(self, p):
+ """ type_qualifier_list : type_qualifier
+ | type_qualifier_list type_qualifier
+ """
+ p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]]
+
+ def p_parameter_type_list(self, p):
+ """ parameter_type_list : parameter_list
+ | parameter_list COMMA ELLIPSIS
+ """
+ if len(p) > 2:
+ p[1].params.append(c_ast.EllipsisParam())
+
+ p[0] = p[1]
+
+ def p_parameter_list(self, p):
+ """ parameter_list : parameter_declaration
+ | parameter_list COMMA parameter_declaration
+ """
+ if len(p) == 2: # single parameter
+ p[0] = c_ast.ParamList([p[1]], p[1].coord)
+ else:
+ p[1].params.append(p[3])
+ p[0] = p[1]
+
+ def p_parameter_declaration_1(self, p):
+ """ parameter_declaration : declaration_specifiers declarator
+ """
+ spec = p[1]
+ decl = p[2]
+
+ decl = c_ast.Decl(
+ name=None,
+ quals=spec['qual'],
+ storage=spec['storage'],
+ funcspec=spec['function'],
+ type=decl,
+ init=None,
+ bitsize=None,
+ coord=decl.coord)
+
+ typename = spec['type'] or ['int']
+ p[0] = self._fix_decl_name_type(decl, typename)
+
+ def p_parameter_declaration_2(self, p):
+ """ parameter_declaration : declaration_specifiers abstract_declarator_opt
+ """
+ spec = p[1]
+ decl = c_ast.Typename(
+ quals=spec['qual'],
+ type=p[2] or c_ast.TypeDecl(None, None, None))
+
+ typename = spec['type'] or ['int']
+ p[0] = self._fix_decl_name_type(decl, typename)
+
+ def p_identifier_list(self, p):
+ """ identifier_list : identifier
+ | identifier_list COMMA identifier
+ """
+ if len(p) == 2: # single parameter
+ p[0] = c_ast.ParamList([p[1]], p[1].coord)
+ else:
+ p[1].params.append(p[3])
+ p[0] = p[1]
+
+ def p_initializer_1(self, p):
+ """ initializer : assignment_expression
+ """
+ p[0] = p[1]
+
+ def p_initializer_2(self, p):
+ """ initializer : LBRACE initializer_list RBRACE
+ | LBRACE initializer_list COMMA RBRACE
+ """
+ p[0] = p[2]
+
+ def p_initializer_list(self, p):
+ """ initializer_list : designation_opt initializer
+ | initializer_list COMMA designation_opt initializer
+ """
+ if len(p) == 3: # single initializer
+ init = p[2] if p[1] is None else c_ast.NamedInitializer(p[1], p[2])
+ p[0] = c_ast.ExprList([init], p[2].coord)
+ else:
+ init = p[4] if p[3] is None else c_ast.NamedInitializer(p[3], p[4])
+ p[1].exprs.append(init)
+ p[0] = p[1]
+
def p_designation(self, p):
""" designation : designator_list EQUALS
- """
- p[0] = p[1]
-
- # Designators are represented as a list of nodes, in the order in which
- # they're written in the code.
- #
+ """
+ p[0] = p[1]
+
+ # Designators are represented as a list of nodes, in the order in which
+ # they're written in the code.
+ #
def p_designator_list(self, p):
- """ designator_list : designator
+ """ designator_list : designator
| designator_list designator
- """
- p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]]
-
+ """
+ p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]]
+
def p_designator(self, p):
- """ designator : LBRACKET constant_expression RBRACKET
+ """ designator : LBRACKET constant_expression RBRACKET
| PERIOD identifier
- """
- p[0] = p[2]
-
- def p_type_name(self, p):
- """ type_name : specifier_qualifier_list abstract_declarator_opt
- """
- #~ print '=========='
- #~ print p[1]
- #~ print p[2]
- #~ print p[2].children()
- #~ print '=========='
-
- typename = c_ast.Typename(
- quals=p[1]['qual'],
- type=p[2] or c_ast.TypeDecl(None, None, None))
-
- p[0] = self._fix_decl_name_type(typename, p[1]['type'])
-
- def p_abstract_declarator_1(self, p):
- """ abstract_declarator : pointer
- """
- dummytype = c_ast.TypeDecl(None, None, None)
- p[0] = self._type_modify_decl(
- decl=dummytype,
- modifier=p[1])
-
- def p_abstract_declarator_2(self, p):
- """ abstract_declarator : pointer direct_abstract_declarator
- """
- p[0] = self._type_modify_decl(p[2], p[1])
-
- def p_abstract_declarator_3(self, p):
- """ abstract_declarator : direct_abstract_declarator
- """
- p[0] = p[1]
-
- # Creating and using direct_abstract_declarator_opt here
- # instead of listing both direct_abstract_declarator and the
- # lack of it in the beginning of _1 and _2 caused two
- # shift/reduce errors.
- #
- def p_direct_abstract_declarator_1(self, p):
- """ direct_abstract_declarator : LPAREN abstract_declarator RPAREN """
- p[0] = p[2]
-
- def p_direct_abstract_declarator_2(self, p):
- """ direct_abstract_declarator : direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET
- """
- arr = c_ast.ArrayDecl(
- type=None,
- dim=p[3],
- coord=p[1].coord)
-
- p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
-
- def p_direct_abstract_declarator_3(self, p):
- """ direct_abstract_declarator : LBRACKET assignment_expression_opt RBRACKET
- """
- p[0] = c_ast.ArrayDecl(
- type=c_ast.TypeDecl(None, None, None),
- dim=p[2],
- coord=self._coord(p.lineno(1)))
-
- def p_direct_abstract_declarator_4(self, p):
- """ direct_abstract_declarator : direct_abstract_declarator LBRACKET TIMES RBRACKET
- """
- arr = c_ast.ArrayDecl(
- type=None,
- dim=c_ast.ID(p[3], self._coord(p.lineno(3))),
- coord=p[1].coord)
-
- p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
-
- def p_direct_abstract_declarator_5(self, p):
- """ direct_abstract_declarator : LBRACKET TIMES RBRACKET
- """
- p[0] = c_ast.ArrayDecl(
- type=c_ast.TypeDecl(None, None, None),
- dim=c_ast.ID(p[3], self._coord(p.lineno(3))),
- coord=self._coord(p.lineno(1)))
-
- def p_direct_abstract_declarator_6(self, p):
- """ direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN
- """
- func = c_ast.FuncDecl(
- args=p[3],
- type=None,
- coord=p[1].coord)
-
- p[0] = self._type_modify_decl(decl=p[1], modifier=func)
-
- def p_direct_abstract_declarator_7(self, p):
- """ direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN
- """
- p[0] = c_ast.FuncDecl(
- args=p[2],
- type=c_ast.TypeDecl(None, None, None),
- coord=self._coord(p.lineno(1)))
-
- # declaration is a list, statement isn't. To make it consistent, block_item
- # will always be a list
- #
+ """
+ p[0] = p[2]
+
+ def p_type_name(self, p):
+ """ type_name : specifier_qualifier_list abstract_declarator_opt
+ """
+ #~ print '=========='
+ #~ print p[1]
+ #~ print p[2]
+ #~ print p[2].children()
+ #~ print '=========='
+
+ typename = c_ast.Typename(
+ quals=p[1]['qual'],
+ type=p[2] or c_ast.TypeDecl(None, None, None))
+
+ p[0] = self._fix_decl_name_type(typename, p[1]['type'])
+
+ def p_abstract_declarator_1(self, p):
+ """ abstract_declarator : pointer
+ """
+ dummytype = c_ast.TypeDecl(None, None, None)
+ p[0] = self._type_modify_decl(
+ decl=dummytype,
+ modifier=p[1])
+
+ def p_abstract_declarator_2(self, p):
+ """ abstract_declarator : pointer direct_abstract_declarator
+ """
+ p[0] = self._type_modify_decl(p[2], p[1])
+
+ def p_abstract_declarator_3(self, p):
+ """ abstract_declarator : direct_abstract_declarator
+ """
+ p[0] = p[1]
+
+ # Creating and using direct_abstract_declarator_opt here
+ # instead of listing both direct_abstract_declarator and the
+ # lack of it in the beginning of _1 and _2 caused two
+ # shift/reduce errors.
+ #
+ def p_direct_abstract_declarator_1(self, p):
+ """ direct_abstract_declarator : LPAREN abstract_declarator RPAREN """
+ p[0] = p[2]
+
+ def p_direct_abstract_declarator_2(self, p):
+ """ direct_abstract_declarator : direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET
+ """
+ arr = c_ast.ArrayDecl(
+ type=None,
+ dim=p[3],
+ coord=p[1].coord)
+
+ p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
+
+ def p_direct_abstract_declarator_3(self, p):
+ """ direct_abstract_declarator : LBRACKET assignment_expression_opt RBRACKET
+ """
+ p[0] = c_ast.ArrayDecl(
+ type=c_ast.TypeDecl(None, None, None),
+ dim=p[2],
+ coord=self._coord(p.lineno(1)))
+
+ def p_direct_abstract_declarator_4(self, p):
+ """ direct_abstract_declarator : direct_abstract_declarator LBRACKET TIMES RBRACKET
+ """
+ arr = c_ast.ArrayDecl(
+ type=None,
+ dim=c_ast.ID(p[3], self._coord(p.lineno(3))),
+ coord=p[1].coord)
+
+ p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
+
+ def p_direct_abstract_declarator_5(self, p):
+ """ direct_abstract_declarator : LBRACKET TIMES RBRACKET
+ """
+ p[0] = c_ast.ArrayDecl(
+ type=c_ast.TypeDecl(None, None, None),
+ dim=c_ast.ID(p[3], self._coord(p.lineno(3))),
+ coord=self._coord(p.lineno(1)))
+
+ def p_direct_abstract_declarator_6(self, p):
+ """ direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN
+ """
+ func = c_ast.FuncDecl(
+ args=p[3],
+ type=None,
+ coord=p[1].coord)
+
+ p[0] = self._type_modify_decl(decl=p[1], modifier=func)
+
+ def p_direct_abstract_declarator_7(self, p):
+ """ direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN
+ """
+ p[0] = c_ast.FuncDecl(
+ args=p[2],
+ type=c_ast.TypeDecl(None, None, None),
+ coord=self._coord(p.lineno(1)))
+
+ # declaration is a list, statement isn't. To make it consistent, block_item
+ # will always be a list
+ #
def p_block_item(self, p):
- """ block_item : declaration
+ """ block_item : declaration
| statement
- """
- p[0] = p[1] if isinstance(p[1], list) else [p[1]]
-
- # Since we made block_item a list, this just combines lists
- #
- def p_block_item_list(self, p):
- """ block_item_list : block_item
- | block_item_list block_item
- """
- p[0] = p[1] if len(p) == 2 else p[1] + p[2]
-
- def p_compound_statement_1(self, p):
- """ compound_statement : LBRACE block_item_list_opt RBRACE """
- p[0] = c_ast.Compound(
- block_items=p[2],
- coord=self._coord(p.lineno(1)))
-
- def p_labeled_statement_1(self, p):
- """ labeled_statement : ID COLON statement """
- p[0] = c_ast.Label(p[1], p[3], self._coord(p.lineno(1)))
-
- def p_labeled_statement_2(self, p):
- """ labeled_statement : CASE constant_expression COLON statement """
- p[0] = c_ast.Case(p[2], p[4], self._coord(p.lineno(1)))
-
- def p_labeled_statement_3(self, p):
- """ labeled_statement : DEFAULT COLON statement """
- p[0] = c_ast.Default(p[3], self._coord(p.lineno(1)))
-
- def p_selection_statement_1(self, p):
- """ selection_statement : IF LPAREN expression RPAREN statement """
- p[0] = c_ast.If(p[3], p[5], None, self._coord(p.lineno(1)))
-
- def p_selection_statement_2(self, p):
- """ selection_statement : IF LPAREN expression RPAREN statement ELSE statement """
- p[0] = c_ast.If(p[3], p[5], p[7], self._coord(p.lineno(1)))
-
- def p_selection_statement_3(self, p):
- """ selection_statement : SWITCH LPAREN expression RPAREN statement """
- p[0] = c_ast.Switch(p[3], p[5], self._coord(p.lineno(1)))
-
- def p_iteration_statement_1(self, p):
- """ iteration_statement : WHILE LPAREN expression RPAREN statement """
- p[0] = c_ast.While(p[3], p[5], self._coord(p.lineno(1)))
-
- def p_iteration_statement_2(self, p):
- """ iteration_statement : DO statement WHILE LPAREN expression RPAREN SEMI """
- p[0] = c_ast.DoWhile(p[5], p[2], self._coord(p.lineno(1)))
-
- def p_iteration_statement_3(self, p):
- """ iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement """
- p[0] = c_ast.For(p[3], p[5], p[7], p[9], self._coord(p.lineno(1)))
-
- def p_iteration_statement_4(self, p):
- """ iteration_statement : FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement """
- p[0] = c_ast.For(c_ast.DeclList(p[3]), p[4], p[6], p[8], self._coord(p.lineno(1)))
-
- def p_jump_statement_1(self, p):
- """ jump_statement : GOTO ID SEMI """
- p[0] = c_ast.Goto(p[2], self._coord(p.lineno(1)))
-
- def p_jump_statement_2(self, p):
- """ jump_statement : BREAK SEMI """
- p[0] = c_ast.Break(self._coord(p.lineno(1)))
-
- def p_jump_statement_3(self, p):
- """ jump_statement : CONTINUE SEMI """
- p[0] = c_ast.Continue(self._coord(p.lineno(1)))
-
- def p_jump_statement_4(self, p):
- """ jump_statement : RETURN expression SEMI
- | RETURN SEMI
- """
- p[0] = c_ast.Return(p[2] if len(p) == 4 else None, self._coord(p.lineno(1)))
-
- def p_expression_statement(self, p):
- """ expression_statement : expression_opt SEMI """
- p[0] = p[1]
-
- def p_expression(self, p):
- """ expression : assignment_expression
- | expression COMMA assignment_expression
- """
- if len(p) == 2:
- p[0] = p[1]
- else:
- if not isinstance(p[1], c_ast.ExprList):
- p[1] = c_ast.ExprList([p[1]], p[1].coord)
-
- p[1].exprs.append(p[3])
- p[0] = p[1]
-
- def p_typedef_name(self, p):
- """ typedef_name : TYPEID """
- p[0] = p[1]
-
- def p_assignment_expression(self, p):
- """ assignment_expression : conditional_expression
- | unary_expression assignment_operator assignment_expression
- """
- if len(p) == 2:
- p[0] = p[1]
- else:
- p[0] = c_ast.Assignment(p[2], p[1], p[3], p[1].coord)
-
- # K&R2 defines these as many separate rules, to encode
- # precedence and associativity. Why work hard ? I'll just use
- # the built in precedence/associativity specification feature
- # of PLY. (see precedence declaration above)
- #
- def p_assignment_operator(self, p):
- """ assignment_operator : EQUALS
- | XOREQUAL
- | TIMESEQUAL
- | DIVEQUAL
- | MODEQUAL
- | PLUSEQUAL
- | MINUSEQUAL
- | LSHIFTEQUAL
- | RSHIFTEQUAL
- | ANDEQUAL
- | OREQUAL
- """
- p[0] = p[1]
-
- def p_constant_expression(self, p):
- """ constant_expression : conditional_expression """
- p[0] = p[1]
-
- def p_conditional_expression(self, p):
- """ conditional_expression : binary_expression
- | binary_expression CONDOP expression COLON conditional_expression
- """
- if len(p) == 2:
- p[0] = p[1]
- else:
- p[0] = c_ast.TernaryOp(p[1], p[3], p[5], p[1].coord)
-
- def p_binary_expression(self, p):
- """ binary_expression : cast_expression
- | binary_expression TIMES binary_expression
- | binary_expression DIVIDE binary_expression
- | binary_expression MOD binary_expression
- | binary_expression PLUS binary_expression
- | binary_expression MINUS binary_expression
- | binary_expression RSHIFT binary_expression
- | binary_expression LSHIFT binary_expression
- | binary_expression LT binary_expression
- | binary_expression LE binary_expression
- | binary_expression GE binary_expression
- | binary_expression GT binary_expression
- | binary_expression EQ binary_expression
- | binary_expression NE binary_expression
- | binary_expression AND binary_expression
- | binary_expression OR binary_expression
- | binary_expression XOR binary_expression
- | binary_expression LAND binary_expression
- | binary_expression LOR binary_expression
- """
- if len(p) == 2:
- p[0] = p[1]
- else:
- p[0] = c_ast.BinaryOp(p[2], p[1], p[3], p[1].coord)
-
- def p_cast_expression_1(self, p):
- """ cast_expression : unary_expression """
- p[0] = p[1]
-
- def p_cast_expression_2(self, p):
- """ cast_expression : LPAREN type_name RPAREN cast_expression """
- p[0] = c_ast.Cast(p[2], p[4], p[2].coord)
-
- def p_unary_expression_1(self, p):
- """ unary_expression : postfix_expression """
- p[0] = p[1]
-
- def p_unary_expression_2(self, p):
- """ unary_expression : PLUSPLUS unary_expression
- | MINUSMINUS unary_expression
- | unary_operator cast_expression
- """
- p[0] = c_ast.UnaryOp(p[1], p[2], p[2].coord)
-
- def p_unary_expression_3(self, p):
- """ unary_expression : SIZEOF unary_expression
- | SIZEOF LPAREN type_name RPAREN
- """
- p[0] = c_ast.UnaryOp(
- p[1],
- p[2] if len(p) == 3 else p[3],
- self._coord(p.lineno(1)))
-
- def p_unary_operator(self, p):
- """ unary_operator : AND
- | TIMES
- | PLUS
- | MINUS
- | NOT
- | LNOT
- """
- p[0] = p[1]
-
- def p_postfix_exptession_1(self, p):
- """ postfix_expression : primary_expression """
- p[0] = p[1]
-
- def p_postfix_exptession_2(self, p):
- """ postfix_expression : postfix_expression LBRACKET expression RBRACKET """
- p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord)
-
- def p_postfix_exptession_3(self, p):
- """ postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN
- | postfix_expression LPAREN RPAREN
- """
- p[0] = c_ast.FuncCall(p[1], p[3] if len(p) == 5 else None, p[1].coord)
-
- def p_postfix_expression_4(self, p):
- """ postfix_expression : postfix_expression PERIOD identifier
- | postfix_expression ARROW identifier
- """
- p[0] = c_ast.StructRef(p[1], p[2], p[3], p[1].coord)
-
- def p_postfix_expression_5(self, p):
- """ postfix_expression : postfix_expression PLUSPLUS
- | postfix_expression MINUSMINUS
- """
- p[0] = c_ast.UnaryOp('p' + p[2], p[1], p[1].coord)
-
+ """
+ p[0] = p[1] if isinstance(p[1], list) else [p[1]]
+
+ # Since we made block_item a list, this just combines lists
+ #
+ def p_block_item_list(self, p):
+ """ block_item_list : block_item
+ | block_item_list block_item
+ """
+ p[0] = p[1] if len(p) == 2 else p[1] + p[2]
+
+ def p_compound_statement_1(self, p):
+ """ compound_statement : LBRACE block_item_list_opt RBRACE """
+ p[0] = c_ast.Compound(
+ block_items=p[2],
+ coord=self._coord(p.lineno(1)))
+
+ def p_labeled_statement_1(self, p):
+ """ labeled_statement : ID COLON statement """
+ p[0] = c_ast.Label(p[1], p[3], self._coord(p.lineno(1)))
+
+ def p_labeled_statement_2(self, p):
+ """ labeled_statement : CASE constant_expression COLON statement """
+ p[0] = c_ast.Case(p[2], p[4], self._coord(p.lineno(1)))
+
+ def p_labeled_statement_3(self, p):
+ """ labeled_statement : DEFAULT COLON statement """
+ p[0] = c_ast.Default(p[3], self._coord(p.lineno(1)))
+
+ def p_selection_statement_1(self, p):
+ """ selection_statement : IF LPAREN expression RPAREN statement """
+ p[0] = c_ast.If(p[3], p[5], None, self._coord(p.lineno(1)))
+
+ def p_selection_statement_2(self, p):
+ """ selection_statement : IF LPAREN expression RPAREN statement ELSE statement """
+ p[0] = c_ast.If(p[3], p[5], p[7], self._coord(p.lineno(1)))
+
+ def p_selection_statement_3(self, p):
+ """ selection_statement : SWITCH LPAREN expression RPAREN statement """
+ p[0] = c_ast.Switch(p[3], p[5], self._coord(p.lineno(1)))
+
+ def p_iteration_statement_1(self, p):
+ """ iteration_statement : WHILE LPAREN expression RPAREN statement """
+ p[0] = c_ast.While(p[3], p[5], self._coord(p.lineno(1)))
+
+ def p_iteration_statement_2(self, p):
+ """ iteration_statement : DO statement WHILE LPAREN expression RPAREN SEMI """
+ p[0] = c_ast.DoWhile(p[5], p[2], self._coord(p.lineno(1)))
+
+ def p_iteration_statement_3(self, p):
+ """ iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement """
+ p[0] = c_ast.For(p[3], p[5], p[7], p[9], self._coord(p.lineno(1)))
+
+ def p_iteration_statement_4(self, p):
+ """ iteration_statement : FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement """
+ p[0] = c_ast.For(c_ast.DeclList(p[3]), p[4], p[6], p[8], self._coord(p.lineno(1)))
+
+ def p_jump_statement_1(self, p):
+ """ jump_statement : GOTO ID SEMI """
+ p[0] = c_ast.Goto(p[2], self._coord(p.lineno(1)))
+
+ def p_jump_statement_2(self, p):
+ """ jump_statement : BREAK SEMI """
+ p[0] = c_ast.Break(self._coord(p.lineno(1)))
+
+ def p_jump_statement_3(self, p):
+ """ jump_statement : CONTINUE SEMI """
+ p[0] = c_ast.Continue(self._coord(p.lineno(1)))
+
+ def p_jump_statement_4(self, p):
+ """ jump_statement : RETURN expression SEMI
+ | RETURN SEMI
+ """
+ p[0] = c_ast.Return(p[2] if len(p) == 4 else None, self._coord(p.lineno(1)))
+
+ def p_expression_statement(self, p):
+ """ expression_statement : expression_opt SEMI """
+ p[0] = p[1]
+
+ def p_expression(self, p):
+ """ expression : assignment_expression
+ | expression COMMA assignment_expression
+ """
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ if not isinstance(p[1], c_ast.ExprList):
+ p[1] = c_ast.ExprList([p[1]], p[1].coord)
+
+ p[1].exprs.append(p[3])
+ p[0] = p[1]
+
+ def p_typedef_name(self, p):
+ """ typedef_name : TYPEID """
+ p[0] = p[1]
+
+ def p_assignment_expression(self, p):
+ """ assignment_expression : conditional_expression
+ | unary_expression assignment_operator assignment_expression
+ """
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = c_ast.Assignment(p[2], p[1], p[3], p[1].coord)
+
+ # K&R2 defines these as many separate rules, to encode
+ # precedence and associativity. Why work hard ? I'll just use
+ # the built in precedence/associativity specification feature
+ # of PLY. (see precedence declaration above)
+ #
+ def p_assignment_operator(self, p):
+ """ assignment_operator : EQUALS
+ | XOREQUAL
+ | TIMESEQUAL
+ | DIVEQUAL
+ | MODEQUAL
+ | PLUSEQUAL
+ | MINUSEQUAL
+ | LSHIFTEQUAL
+ | RSHIFTEQUAL
+ | ANDEQUAL
+ | OREQUAL
+ """
+ p[0] = p[1]
+
+ def p_constant_expression(self, p):
+ """ constant_expression : conditional_expression """
+ p[0] = p[1]
+
+ def p_conditional_expression(self, p):
+ """ conditional_expression : binary_expression
+ | binary_expression CONDOP expression COLON conditional_expression
+ """
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = c_ast.TernaryOp(p[1], p[3], p[5], p[1].coord)
+
+ def p_binary_expression(self, p):
+ """ binary_expression : cast_expression
+ | binary_expression TIMES binary_expression
+ | binary_expression DIVIDE binary_expression
+ | binary_expression MOD binary_expression
+ | binary_expression PLUS binary_expression
+ | binary_expression MINUS binary_expression
+ | binary_expression RSHIFT binary_expression
+ | binary_expression LSHIFT binary_expression
+ | binary_expression LT binary_expression
+ | binary_expression LE binary_expression
+ | binary_expression GE binary_expression
+ | binary_expression GT binary_expression
+ | binary_expression EQ binary_expression
+ | binary_expression NE binary_expression
+ | binary_expression AND binary_expression
+ | binary_expression OR binary_expression
+ | binary_expression XOR binary_expression
+ | binary_expression LAND binary_expression
+ | binary_expression LOR binary_expression
+ """
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = c_ast.BinaryOp(p[2], p[1], p[3], p[1].coord)
+
+ def p_cast_expression_1(self, p):
+ """ cast_expression : unary_expression """
+ p[0] = p[1]
+
+ def p_cast_expression_2(self, p):
+ """ cast_expression : LPAREN type_name RPAREN cast_expression """
+ p[0] = c_ast.Cast(p[2], p[4], p[2].coord)
+
+ def p_unary_expression_1(self, p):
+ """ unary_expression : postfix_expression """
+ p[0] = p[1]
+
+ def p_unary_expression_2(self, p):
+ """ unary_expression : PLUSPLUS unary_expression
+ | MINUSMINUS unary_expression
+ | unary_operator cast_expression
+ """
+ p[0] = c_ast.UnaryOp(p[1], p[2], p[2].coord)
+
+ def p_unary_expression_3(self, p):
+ """ unary_expression : SIZEOF unary_expression
+ | SIZEOF LPAREN type_name RPAREN
+ """
+ p[0] = c_ast.UnaryOp(
+ p[1],
+ p[2] if len(p) == 3 else p[3],
+ self._coord(p.lineno(1)))
+
+ def p_unary_operator(self, p):
+ """ unary_operator : AND
+ | TIMES
+ | PLUS
+ | MINUS
+ | NOT
+ | LNOT
+ """
+ p[0] = p[1]
+
+ def p_postfix_exptession_1(self, p):
+ """ postfix_expression : primary_expression """
+ p[0] = p[1]
+
+ def p_postfix_exptession_2(self, p):
+ """ postfix_expression : postfix_expression LBRACKET expression RBRACKET """
+ p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord)
+
+ def p_postfix_exptession_3(self, p):
+ """ postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN
+ | postfix_expression LPAREN RPAREN
+ """
+ p[0] = c_ast.FuncCall(p[1], p[3] if len(p) == 5 else None, p[1].coord)
+
+ def p_postfix_expression_4(self, p):
+ """ postfix_expression : postfix_expression PERIOD identifier
+ | postfix_expression ARROW identifier
+ """
+ p[0] = c_ast.StructRef(p[1], p[2], p[3], p[1].coord)
+
+ def p_postfix_expression_5(self, p):
+ """ postfix_expression : postfix_expression PLUSPLUS
+ | postfix_expression MINUSMINUS
+ """
+ p[0] = c_ast.UnaryOp('p' + p[2], p[1], p[1].coord)
+
def p_postfix_expression_6(self, p):
- """ postfix_expression : LPAREN type_name RPAREN LBRACE initializer_list RBRACE
- | LPAREN type_name RPAREN LBRACE initializer_list COMMA RBRACE
- """
- p[0] = c_ast.CompoundLiteral(p[2], p[5])
-
- def p_primary_expression_1(self, p):
- """ primary_expression : identifier """
- p[0] = p[1]
-
- def p_primary_expression_2(self, p):
- """ primary_expression : constant """
- p[0] = p[1]
-
- def p_primary_expression_3(self, p):
- """ primary_expression : unified_string_literal
- | unified_wstring_literal
- """
- p[0] = p[1]
-
- def p_primary_expression_4(self, p):
- """ primary_expression : LPAREN expression RPAREN """
- p[0] = p[2]
-
- def p_argument_expression_list(self, p):
- """ argument_expression_list : assignment_expression
- | argument_expression_list COMMA assignment_expression
- """
- if len(p) == 2: # single expr
- p[0] = c_ast.ExprList([p[1]], p[1].coord)
- else:
- p[1].exprs.append(p[3])
- p[0] = p[1]
-
- def p_identifier(self, p):
- """ identifier : ID """
- p[0] = c_ast.ID(p[1], self._coord(p.lineno(1)))
-
- def p_constant_1(self, p):
- """ constant : INT_CONST_DEC
- | INT_CONST_OCT
- | INT_CONST_HEX
- """
- p[0] = c_ast.Constant(
- 'int', p[1], self._coord(p.lineno(1)))
-
- def p_constant_2(self, p):
- """ constant : FLOAT_CONST """
- p[0] = c_ast.Constant(
- 'float', p[1], self._coord(p.lineno(1)))
-
- def p_constant_3(self, p):
- """ constant : CHAR_CONST
- | WCHAR_CONST
- """
- p[0] = c_ast.Constant(
- 'char', p[1], self._coord(p.lineno(1)))
-
- # The "unified" string and wstring literal rules are for supporting
- # concatenation of adjacent string literals.
- # I.e. "hello " "world" is seen by the C compiler as a single string literal
- # with the value "hello world"
- #
+ """ postfix_expression : LPAREN type_name RPAREN LBRACE initializer_list RBRACE
+ | LPAREN type_name RPAREN LBRACE initializer_list COMMA RBRACE
+ """
+ p[0] = c_ast.CompoundLiteral(p[2], p[5])
+
+ def p_primary_expression_1(self, p):
+ """ primary_expression : identifier """
+ p[0] = p[1]
+
+ def p_primary_expression_2(self, p):
+ """ primary_expression : constant """
+ p[0] = p[1]
+
+ def p_primary_expression_3(self, p):
+ """ primary_expression : unified_string_literal
+ | unified_wstring_literal
+ """
+ p[0] = p[1]
+
+ def p_primary_expression_4(self, p):
+ """ primary_expression : LPAREN expression RPAREN """
+ p[0] = p[2]
+
+ def p_argument_expression_list(self, p):
+ """ argument_expression_list : assignment_expression
+ | argument_expression_list COMMA assignment_expression
+ """
+ if len(p) == 2: # single expr
+ p[0] = c_ast.ExprList([p[1]], p[1].coord)
+ else:
+ p[1].exprs.append(p[3])
+ p[0] = p[1]
+
+ def p_identifier(self, p):
+ """ identifier : ID """
+ p[0] = c_ast.ID(p[1], self._coord(p.lineno(1)))
+
+ def p_constant_1(self, p):
+ """ constant : INT_CONST_DEC
+ | INT_CONST_OCT
+ | INT_CONST_HEX
+ """
+ p[0] = c_ast.Constant(
+ 'int', p[1], self._coord(p.lineno(1)))
+
+ def p_constant_2(self, p):
+ """ constant : FLOAT_CONST """
+ p[0] = c_ast.Constant(
+ 'float', p[1], self._coord(p.lineno(1)))
+
+ def p_constant_3(self, p):
+ """ constant : CHAR_CONST
+ | WCHAR_CONST
+ """
+ p[0] = c_ast.Constant(
+ 'char', p[1], self._coord(p.lineno(1)))
+
+ # The "unified" string and wstring literal rules are for supporting
+ # concatenation of adjacent string literals.
+ # I.e. "hello " "world" is seen by the C compiler as a single string literal
+ # with the value "hello world"
+ #
def p_unified_string_literal(self, p):
- """ unified_string_literal : STRING_LITERAL
+ """ unified_string_literal : STRING_LITERAL
| unified_string_literal STRING_LITERAL
- """
- if len(p) == 2: # single literal
- p[0] = c_ast.Constant(
- 'string', p[1], self._coord(p.lineno(1)))
- else:
- p[1].value = p[1].value[:-1] + p[2][1:]
- p[0] = p[1]
-
- def p_unified_wstring_literal(self, p):
- """ unified_wstring_literal : WSTRING_LITERAL
- | unified_wstring_literal WSTRING_LITERAL
- """
- if len(p) == 2: # single literal
- p[0] = c_ast.Constant(
- 'string', p[1], self._coord(p.lineno(1)))
- else:
- p[1].value = p[1].value.rstrip[:-1] + p[2][1:]
- p[0] = p[1]
-
- def p_empty(self, p):
- 'empty : '
- p[0] = None
-
- def p_error(self, p):
- if p:
- self._parse_error(
- 'before: %s' % p.value,
- self._coord(p.lineno))
- else:
- self._parse_error('At end of input', '')
-
-
-if __name__ == "__main__":
- import pprint
- import time
- from portability import printme
-
- t1 = time.time()
- parser = CParser(lex_optimize=True, yacc_debug=True, yacc_optimize=False)
- printme(time.time() - t1)
-
- buf = '''
- int (*k)(int);
- '''
-
- # set debuglevel to 2 for debugging
- t = parser.parse(buf, 'x.c', debuglevel=0)
- t.show(showcoord=True)
+ """
+ if len(p) == 2: # single literal
+ p[0] = c_ast.Constant(
+ 'string', p[1], self._coord(p.lineno(1)))
+ else:
+ p[1].value = p[1].value[:-1] + p[2][1:]
+ p[0] = p[1]
+
+ def p_unified_wstring_literal(self, p):
+ """ unified_wstring_literal : WSTRING_LITERAL
+ | unified_wstring_literal WSTRING_LITERAL
+ """
+ if len(p) == 2: # single literal
+ p[0] = c_ast.Constant(
+ 'string', p[1], self._coord(p.lineno(1)))
+ else:
+ p[1].value = p[1].value.rstrip[:-1] + p[2][1:]
+ p[0] = p[1]
+
+ def p_empty(self, p):
+ 'empty : '
+ p[0] = None
+
+ def p_error(self, p):
+ if p:
+ self._parse_error(
+ 'before: %s' % p.value,
+ self._coord(p.lineno))
+ else:
+ self._parse_error('At end of input', '')
+
+
+if __name__ == "__main__":
+ import pprint
+ import time
+ from portability import printme
+
+ t1 = time.time()
+ parser = CParser(lex_optimize=True, yacc_debug=True, yacc_optimize=False)
+ printme(time.time() - t1)
+
+ buf = '''
+ int (*k)(int);
+ '''
+
+ # set debuglevel to 2 for debugging
+ t = parser.parse(buf, 'x.c', debuglevel=0)
+ t.show(showcoord=True)
diff --git a/setup.py b/setup.py
index 3d7b72e..e4a348d 100644
--- a/setup.py
+++ b/setup.py
@@ -13,7 +13,7 @@ setup(
C compilers or analysis tools.
""",
license='LGPL',
- version='2.00',
+ version='2.01',
author='Eli Bendersky',
maintainer='Eli Bendersky',
author_email='eliben@gmail.com',
@@ -21,7 +21,7 @@ setup(
platforms='Cross Platform',
packages=['pycparser'],
- package_data={'pycparser': ['*.yaml']},
+ package_data={'pycparser': ['*.cfg']},
)