Note: This article is a work in progress.
I'm partial to C for its simplicity and power, but I prefer to work in an object-oriented mindset when I write code. I'm no fan of the hot mess is C++, however. So I was quite excited when I found Objective C a few years ago. Although from a syntactical standpoint, the language is clearly an imposition on the underlying C syntax, I think the overall effect is more intuitive and elegant than the Arcane Wizard Scrawl(TM) that C++ has become. I'd hoped to start using Objective C, by way of GCC, as my main programming language -- but their desire to keep pace with Apple's slow destruction of the language ruined those plans.
In an effort to find an alternative, I stumbled across the Portable Object Compiler. The basic syntax is the same as what Apple brought out of NeXT, except that protocols (interfaces) are not supported -- though there are ways to live without this -- and categories have to be implemented in a different fashion, albeit one that makes sense.
Intrigued, I downloaded the bootstrap compiler and compiler sources and...they didn't compile on my Linux box. Continue reading...
Note: I cannot guarantee that any of the links to Microsoft documents which appear in the following article will continue to work, only that they worked when this article was written. Microsoft's documentation pages appear to move around entirely at the whims of madmen, and a link that works today may result in a 404 error tomorrow. Now you know what your favorite search engine is for.
I was recently asked to determine why a group of machines at work were running slowly. The machines in question exist in a shared environment and are used by multiple individuals throughout the course of a given day. There were a few things causing them to malfunction, but one of the more interesting issues I found was that the users were not logging off when they were finished with the machines; instead, they would walk away and the next person would simply hit "Switch User" to log into them. Therefore multiple disconnected user sessions remained in memory, many with programs still running -- and collectively, these abandoned sessions served as an anchor which weighed down the performance of the machines.
...you run into compiler bugs that prevent successfully compiling your library...
While testing some advanced features of the parsing library in preparation for the next step toward building causerie, this is exactly what happened: an obscure bug with the Free Pascal runtime that seems to defy debugging with GDB and which crashes the program every time it runs. (If you're really interested to know, it seems to have something to do with the way that TObject
handles memory allocation).
It's proven to be a rather large setback for causerie, but it isn't the end of the world. I was already developing a C interface for the libraries, to make them as portable as possible, and if all else fails I can expand upon that to take the whole thing into C. I'll have more information here soon.
Previously: Writing a Command-Line Parser, Part 1
In the previous article, we defined the basic elements that are required in order to produce a parser: tokens, opcodes, the general language syntax, statements, expressions, and symbols. Tokens and opcodes are fairly similar across parser implementations, typically differing only in the types of characters allowed to be part of a token and in the data type used to represent the corresponding opcode. The next item that must be addressed, then, is the syntax of LinearC, our command-line argument "language". The syntax will inform the opcodes used and the types of statement and expression handlers we must define. It will also help the tokenizer to correctly classify the tokens read from the command line. Continue reading...
As with other compilers, causerie will need to accept a variety of command-line arguments from the user, or from make
on behalf of the user. This necessity provides with an excellent opportunity to test and fine-tune the base libraries before we tackle the more complex task of parsing a full-fledged computer language.
Why use command-line arguments at all? Unless you have written a very simple program, it is likely that you will want some way to adjust the behavior of your code based on some event or circumstance which you cannot know at the time the program is compiled. You could try to make a list of such circumstances and try to compile an iteration of your code for each one of them, but that entails a high degree of effort which is largely wasteful, since it is simpler to allow the user of your code to indicate what behaviors are desired. Command-line arguments provide a way to do this, as do configuration files, but command-line arguments take up less space and are more portable, since they do not require an additional file besides the executable itself. Since simplicity is one of causerie's goals, we will use command-line arguments instead of a separate configuration file.
Causerie's parsing design is flexible enough that it can be adapted to other uses, such as parsing command-line arguments; thus, while there are libraries already available for this purpose, such as the getops
unit that comes as part of Free Pascal's runtime library, utilizing the libraries we already have for a simple case like parsing command-line arguments will allow us to find bugs and ensure that the parser can handle a more complex task.
Continue reading...