Re: Wrestling with phase 1 of a C compiler

luser droog <>
Wed, 14 Sep 2022 14:31:48 -0700 (PDT)

          From comp.compilers

Related articles
Wrestling with phase 1 of a C compiler (luser droog) (2022-09-07)
Re: Wrestling with phase 1 of a C compiler (luser droog) (2022-09-09)
Re: Wrestling with phase 1 of a C compiler (luser droog) (2022-09-11)
Wrestling with phase 1 of a C compiler (Christopher F Clark) (2022-09-12)
Re: Wrestling with phase 1 of a C compiler (gah4) (2022-09-12)
Re: Wrestling with phase 1 of a C compiler (Christopher F Clark) (2022-09-13)
Re: Wrestling with phase 1 of a C compiler (luser droog) (2022-09-14)
Re: Wrestling with phase 1 of a C compiler (gah4) (2022-09-14)
Re: Wrestling with phase 1 of a C compiler (luser droog) (2022-09-15)
| List of all articles for this month |

From: luser droog <>
Newsgroups: comp.compilers
Date: Wed, 14 Sep 2022 14:31:48 -0700 (PDT)
Organization: Compilers Central
References: 22-09-001 22-09-004
Injection-Info:; posting-host=""; logging-data="97850"; mail-complaints-to=""
Keywords: parse,design
Posted-Date: 15 Sep 2022 12:17:45 EDT
In-Reply-To: 22-09-004

On Monday, September 12, 2022 at 2:46:47 PM UTC-5, wrote:
> While I hate being extremely pessimistic, you are going in absolutely the
> wrong direction.
> If you want a functional language, use one. Don't try to turn C into a
> functional language. Even if you succeed, you will have made a mess that
> no one (probably not even you) will actually understand.

You may be right. But, but but ... I'm in too deep. And I've adopted a "larger
scale methodology" where every time it becomes a mess, I stop. I go back
to the papers by Hutton et al. I make new prototypes in my favorite dynamic
language. And then I go back and merge the new ideas with the best parts
of the old code and produce a new draft. It's getting better.

And my last comment about using the preprocessor might have given a
false clue about what I've been doing. I'm using a few preprocessor tricks
(PP_NARG, X-Macros) but their usage has also evolved through the rewrites.
And I daresay the usage of preprocessor in my code is fairly tame and
readable. Particularly if I were to throw in a link to my SO post which explains
exactly how I use the X-Macros:

> I say that from experience. Early on in writing Yacc++, we did macros that
> allowed us to write object-oriented C, which had C++-like semantics (ala
> 1986, pre-templates, pre STL, etc.) with nice ABC (abstract base classes,
> plus some inheritance and polymorphism). It worked. However, it was a
> challenge to understand. Our wisest move was at 2.0 rewriting everything
> in C++ and not trying to have a "C" layer with similar functionality. The
> code was an order-of-magnitude simpler and even making a translation that
> did C# was relatively trivial from that code.
> C is a nice small imperative language. It's fine for expressing those
> kinds of semantics. The C preprocessor is both simple and powerful, but it
> doesn't change the nature of C. You cannot really do "compilation" in the
> C preprocessor. And, if you really want a parser combinator library, you
> want it to do some compilation. Otherwise, you have just masked the fact
> that you are doing hand-written recursive descent. And, if you want to do
> hand-written recursive descent, do it. Don't put lipstick on a pig and
> take it to the opera.

You're right. I'm not planning on doing it in the preprocessor, but compilation
is one of the big challenges I haven't yet conquered. I have the book by Burge
which has a good description of the algorithms I'll need (I think). But my
in-memory representation might be too clumsy to use directly. I may need to
introduce a symbolic intermediate representation that's easier to do rewrites

You're right that (for now) it's just recursive descent in disguise. But already
it's a pretty guise. The C interface is fairly lightweight and transparent,
iff you can accept the practice of typedefing pointers and treating
certain types as having reference semantics.

> There is a reason your attempts are failing.

Perhaps I'm in too deep to see it this way. But it seems to me that each
draft has failed in a slightly different manner.

>You don't have good closures or co-routines in C.

I think my closures are pretty good. Serviceable, at least. It's an object that
couples a function pointer with it's saved environment.

I don't have co-routines, but I have lists where a node can be a "suspension"
which can transparently (?) invoke the closure to produce elements of
the list lazily. So I have a kind of continuation passing which serves many
of the same uses that I would have for co-routines (unless I'm wrong).

> You cannot get them easily. You cannot really
> interact well with the function stack in C.

That's true. But I can build up graphs of functions and then call the
the thing to run all the doodads.

>And, your efforts to put the
> state behind pointers, while necessary only get you part of the way there.

That's also true. For the present case, I'll also need to dynamically allocate
integer objects and keep them in the environment for the calling
function which is one of these closures, a suspension function that converts
the first element of a stream and returns a list with a suspension in the cdr.

That's the only way I'll get row and column counters to exist on a per-file

> So, if you are lucky, you will have something that looks like a parser
> combinator language, but which actually has either
> - broken semantics (i.e. cases that don't work properly and don't warn you
> that they don't)
> or
> - is very complicated.

If it fails, it fails. I'll try to learn something from it and try something else.
You may indeed be right. But I've steered past the island of the proprocessor
sirens. It's a danger of different kind. Function spaghetti, or maybe
"Function Orzo"(tm).

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.