LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Blogs > astrogeek
User Name
Password

Notices


Rate this Entry

Alphanumeric Calculator: The Source

Posted 10-01-2021 at 07:28 PM by astrogeek
Updated 10-12-2021 at 11:52 AM by astrogeek (Test cases, rearrange page)

Alphanumeric Calculator: The Source

To make it easy to find the source code I have moved the links to the top, along with links to test cases for my code and your build! You will find a brief discussion of the origins of this project below, as well as instructions for building and running the program.

The Source Code

Two source files and a Makefile are all that is required to build this project. Follow each of the links below to copy/paste the source into files with the indicated names in a single directory on your local machine.

Makefile

alphacalc.l - Flex lexer specification source

alphacalc.y - GNU Bison parser specification source (includes application C source)

Test Cases: Sign
Test Cases: Limits
Test Cases: Associativity and Precedence
Test Cases: Optional "and" Handling
Test Cases: Multi-line Input

OK! So what is this all about anyway?

This project is not about the "clever program I wrote"©. Nor is it yet another example of, "Look! More free code!".

This little project is all about the confluence of clever and powerful ideas which come together to make such programs as this example so ordinary, and the enjoyment of discovering and exploring those ideas for ourselves and sharing the experience with others!

The origin, or source of this project was my own far from satisfying first encounters with Lex and YACC in the distant past. At the time I realized that the source of that dissatisfaction (dumbfounded frustration might be a better choice of words) was actually my own lack of understanding of what Lex and YACC provided, the development of the ideas behind them, and how to use both the ideas and the applications derived from them to accomplish some useful task!

As a formal subject this was mostly new territory for me, so I began by reading about the ideas behind tokenizing, lexical analysis, parsing, syntactic analysis, semantic analysis... and a great many other terms I first encountered along the way! Somewhat unexpectedly, I found it all very interesting and continued that research long after my immediate needs had been met! I'll list a few of what I think are the best references on the topic at the end of this post.

As my knowledge of the various subjects and their actual scope initially grew I set the goal of writing my own example parsing project from the ground up, from my own acquired understanding of those first principles not based on any of the examples I encountered along the way. At the time I thought that writing a calculator which communicated through words instead of numbers and math symbols would provide a target of sufficient scope - and it certainly did!

Although it looks simple in retrospect, writing each of the required parts from scratch proved to be an enjoyable and rich source of new understanding, with many "Aha!" moments. It has been an idea to which I have returned several times over the years!

My early code was built around C's strtok() and strtok_r() functions as the basis of my lexer, and various attempts to write a recursive descent parser which might actually implement my (poorly understood) grammars! Although limited and usually incomplete, those exercises were very effective at expanding my own understanding of and ability to work with the underlying ideas, which was the real point. By the time I returned to Lex and YACC (now replaced by Flex and GNU Bison respectively on most platforms) I had a much better understanding of what they actually provided, and how to make more effective use of them.

While moving my older code archives onto a new machine recently, I had a fresh look at my old exercises and realized that I had never actually built a "finished" version, so I thought I'd do the whole exercise again with yet another new grammar, current Flex, Bison and C versions, and extended range of operation, to hopefully end with a more finished application. I recalled the fun of discovery it had always provided and wanted to share that with others. At the same time I wondered how others might approach the same problem, so I posted it as the Programming Challenge: English Speaking Calculator here on LQ.

This post, and the files linked above are my entry into that challenge competition.

I hope that you will find my little program interesting, but I wouldn't suggest that you use it to manage your personal finances!

Instead, I hope that it will be intersting to you in a different way, and prompt you to learn more about the important underlying ideas on which it, and pretty much all of computing as we know it, is ultimately built!

It is more about discovering the path than about arriving at some destination, enjoy your journey!

How To Build and Use

To build the application with debug and trace features built-in run make with DEBUG=1 parameter set:

Code:
make DEBUG=1
  or
make DEBUG=1 alphacalc
To build without debug and trace options simply:

Code:
make
  or
make alphacalc
You may read input from a file by invoking the program with the name of the file, for example:

Code:
$ cat example
/* A few example expressions */
seven times ( thirty three plus negative eighty eight over four)

eleven hundred and twenty minus ninety six

$ ./alphacalc example
seventy seven
one thousand and twenty four
Or run in interactive mode:

Code:
$ ./alphacalc
>Type help for runtime reference info
>help
Input Expression Syntax
        Integer expressions in the range +/-999999999999 may be entered as words or numbers
        Number names: positive, negative, zero...nineteen, twenty...ninety, hundred, thousand, million, billion
                        may be combined into any valid, commonly spoken numeric expression
                Integer values including sign must be atomic: expressed as all english words or as number,
                        may be otherwise mixed in expressions
                Ex: one hundred [and] eleven thousand three hundred [and] twenty two (111322)
                Ex: three million [and] three over three (1000001)
                Ex: one hundred seven plus 3, or 107 + three, but not one hundred 7 plus 3
        Arithmetic Operations and Sign
                plus | + addition ('+' with no trailing space is sign)
                minus | - subtraction ('-' with no trailing space is sign)
                times | * multiplication
                divided by | over | / division
                ( expression ) nested parentheses follow normal precedence rules
        Runtime Options
                alpha | numeric | both : Set output mode
                and : Toggles default trailing 'and' in alpha output (always follows input)
                debug : Toggle parser debug trace mode
                trace : Toggle lexer debug trace mode
                help : Show this help message
                usage : Show invocation help message (same as -h)
                quit : Exit program
>
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 10:52 PM.

Main Menu
Advertisement
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration