The Boston Diaries

The ongoing saga of Sean Conner, who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Thursday, August 06, 2026

Unary operators and the Shunting Yard algorithm

I use the Shunting Yard algorithm to handle precedence when parsing expressions in my assembler. It's great because not only is it simple to implement, but it simplifies the code in a hand-written recursive descent parser. The BNF is effectively:

; BNF per RFC-5234
expr	= factor *(op factor)
op	= '*'	; just the basic ops for now
	/ '/'	; adding more is just adding
	/ '+'	; them to this definition
	/ '-'
factor	=  literal
	/  var
	/  '(' expr ')'
literal	=  DIGIT+
var	=  (ALPHA / '_') (ALPHA / DIGIT / '_')*

When expressing this BNF via a recursive descent parser, the function handling expr is where the Shunting Yard algorithm is used, providing precedence handling. In my implementation, the function handling op returns the precedence and associativity from a table:

static struct optable const cops[] =
{
  [OP_EXP]  = { OP_EXP  , AS_RIGHT , 1000 } ,
  [OP_MUL]  = { OP_MUL  , AS_LEFT  ,  900 } ,
  [OP_DIV]  = { OP_DIV  , AS_LEFT  ,  900 } ,
  [OP_MOD]  = { OP_MOD  , AS_LEFT  ,  900 } ,
  [OP_ADD]  = { OP_ADD  , AS_LEFT  ,  800 } ,
  [OP_SUB]  = { OP_SUB  , AS_LEFT  ,  800 } ,
  [OP_SHL]  = { OP_SHL  , AS_LEFT  ,  700 } ,
  [OP_SHR]  = { OP_SHR  , AS_LEFT  ,  700 } ,
  [OP_BAND] = { OP_BAND , AS_LEFT  ,  600 } ,
  [OP_BEOR] = { OP_BEOR , AS_LEFT  ,  500 } ,
  [OP_BOR]  = { OP_BOR  , AS_LEFT  ,  400 } ,
  [OP_WORD] = { OP_WORD , AS_LEFT  ,  350 } ,
  [OP_NE]   = { OP_NE   , AS_LEFT  ,  300 } ,
  [OP_LT]   = { OP_LT   , AS_LEFT  ,  300 } ,
  [OP_LE]   = { OP_LE   , AS_LEFT  ,  300 } ,
  [OP_EQ]   = { OP_EQ   , AS_LEFT  ,  300 } ,
  [OP_GE]   = { OP_GE   , AS_LEFT  ,  300 } ,
  [OP_GT]   = { OP_GT   , AS_LEFT  ,  300 } ,
  [OP_LAND] = { OP_LAND , AS_LEFT  ,  200 } ,
  [OP_LOR]  = { OP_LOR  , AS_LEFT  ,  100 } ,
};

Adding a new operator is pretty easy. I was able to add the :: operator (OP_WORD) and slot it in (the expression a :: b is the same as a * 256 + b and is used extensively in my 6809 ANS Forth implementation).

The downside, the Shunting Yard algorithm doesn't handle unary operators very well. From what research I've done and a proof-of-concept I did, it can be done. Unary operators need to be right associative, but that's the easy part. It gets ugly with parsing—how to determine if “-” is a subtraction binary operator or a unary negation operator, and where to place that code, and it has to go somewhere. I got it working. but it involved smearing the Shunting Yard algorithm into the op and factor functions in my case. And honesty, I don't think it's worth it just to get -3**2 to return -9 versus 9.


What is even taste when it comes to programming?

[This is me reposting a comment I left on Lobsters about “Taste Is All That's Left,” a post about vibecoding. I think my comments works well enough on its own here as a post. —Sean]

As I read this, I was reminded of two quotes. The first is about the taste gap from Ira Glass:

Nobody tells this to people who are beginners, I wish someone told me. All of us who do creative work, we get into it because we have good taste. But there is this gap. For the first couple years you make stuff, it’s just not that good. It’s trying to be good, it has potential, but it’s not. But your taste, the thing that got you into the game, is still killer. And your taste is why your work disappoints you. A lot of people never get past this phase, they quit. Most people I know who do interesting, creative work went through years of this. We know our work doesn’t have this special thing that we want it to have. We all go through this. And if you are just starting out or you are still in this phase, you gotta know its normal and the most important thing you can do is do a lot of work. Put yourself on a deadline so that every week you will finish one story. It is only by going through a volume of work that you will close that gap, and your work will be as good as your ambitions. And I took longer to figure out how to do this than anyone I’ve ever met. It’s gonna take awhile. It’s normal to take awhile. You’ve just gotta fight your way through.

THE GAP by Ira Glass

The second is from The Ze Frank Show:

For a very long time, taste and artistic training have been things that only a small number of people have been able to develop. Only a few people could afford to participate in the production of many types of media. Raw materials like pigments were expensive; same with tools like printing presses; even as late as 1963 it cost Charles Peignot over $600,000 to create and cut a single font family.

The small number of people who had access to these tools and resources created rules about what was good taste or bad taste. These designers started giving each other awards and the rules they followed became even more specific. All sorts of stuff about grids and sizes and color combinations — lots of stuff that the consumers of this media never consciously noticed. Over the last 20 years, however, the cost of tools related to the authorship of media has plummeted. For very little money, anyone can create and distribute things like newsletters, or videos, or bad-ass tunes about "ugly."

Suddenly consumers are learning the language of these authorship tools. The fact that tons of people know names of fonts like Helvetica is weird! And when people start learning something new, they perceive the world around them differently. If you start learning how to play the guitar, suddenly the guitar stands out in all the music you listen to. For example, throughout most of the history of movies, the audience didn't really understand what a craft editing was. Now, as more and more people have access to things like iMovie, they begin to understand the manipulative power of editing. Watching reality TV almost becomes like a game as you try to second-guess how the editor is trying to manipulate you.

As people start learning and experimenting with these languages authorship, they don't necessarily follow the rules of good taste. This scares the shit out of designers.

the show with zefrank - 2006-07-14

I'm not sure what I make of all this.

Obligatory Picture

[Self-portrait with a Christmas Tree] Oh Chrismtas Tree!  My Christmas Tree!  Rise up and hear the bells!

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

Obligatory AI Disclaimer

No AI was used in the making of this site, unless otherwise noted.

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2026 by Sean Conner. All Rights Reserved.