// Lexical.cpp
// Copyright (c) Friday, April 4, 2025, by
// James Pate Williams, Jr.
// Reference: "Modern Compiler Implementation
// in Java Second Edition" (c) 2002
// Andrew W. Appel with Jens Palsberg
// Chapter Two, Lexical Analysis
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
std::vector<char> AlphabeticChars = { 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
std::vector<char> BracketChars = { '(', ')', '{', '}', '[', ']' };
std::vector<char> ArithmeticOps = { '+', '-', '*', '/', '%' };
std::vector<char> LogicalOps = { '&', '^', '|' };
std::vector<char> DecimalDigits = { '0', '1', '2', '4', '5', '6',
'7', '8', '9' };
std::vector<char> WhiteSpace = { ' ', '\t', '\n' };
std::vector<std::string> ReservedWords = {
"do", "double", "else", "for", "if", "int", "long", "while" };
char reservedWordsAscii[8][8] = { { } };
std::vector<char> AlphaNumericChars;
bool TokenScan(
std::string wline,
bool& arithmeticOp,
bool& bracket,
bool& endOfLine,
bool& id,
bool& intNumber,
bool& logicalOp,
bool& realNumber,
bool& reservedWord,
bool& whiteSpace,
char& arithmeticOpChar,
char& bracketChar,
char& ch,
char& endOfLineChar,
char& whiteSpaceChar,
size_t& cptr,
std::string& idStr,
std::string& intNumberStr,
std::string& realNumberStr,
std::string& reservedWordStr) {
const char* line = wline.c_str();
ch = line[cptr];
while (ch == ' ' || ch == '\t' || ch == '\n' && cptr < strlen(line)) {
cptr++;
ch = line[cptr];
}
if (ch == '\n' || cptr == strlen(line)) {
endOfLine = true;
endOfLineChar = '\n';
return true;
}
ch = line[cptr];
if (ch >= 'A' && ch <= 'Z' ||
ch >= 'a' && ch <= 'z') {
idStr += ch;
cptr++;
while (cptr < strlen(line)) {
ch = line[cptr];
if (ch >= '0' && ch <= '9' ||
ch >= 'A' && ch <= 'Z' ||
ch >= 'a' && ch <= 'z' ||
ch == '_') {
idStr += ch;
cptr++;
}
else if (ch == ' ' || ch == '\t' || ch == '\n') {
cptr++;
break;
}
else {
id = false;
return false;
}
}
id = true;
char reservedWordAscii[8] = { };
reservedWordStr = "";
for (size_t i = 0; i < strlen(idStr.c_str()); i++) {
reservedWordAscii[i] = idStr.c_str()[i];
}
reservedWordAscii[strlen(idStr.c_str())] = '\0';
for (size_t i = 0; i < 8; i++) {
size_t count = 0;
reservedWord = false;
reservedWordStr = "";
for (size_t j = 0; j < strlen(reservedWordsAscii[i]); j++) {
if (reservedWordAscii[j] == reservedWordsAscii[i][j]) {
reservedWord = true;
reservedWordStr += idStr[j];
count++;
}
}
if (reservedWord && count == strlen(reservedWordsAscii[i])) {
break;
}
}
if (reservedWord) {
id = false;
}
if (id) {
id = true;
reservedWord = false;
reservedWordStr = "";
}
else {
id = false;
idStr = "";
}
return id || reservedWord;
}
else if (ch >= '0' && ch <= '9')
{
intNumberStr = "";
realNumberStr = "";
intNumberStr += ch;
realNumberStr += ch;
cptr++;
ch = line[cptr];
if (ch >= '0' && ch <= '9') {
intNumberStr += ch;
cptr++;
ch = line[cptr];
while (cptr < strlen(line)) {
ch = line[cptr];
if (ch >= '0' && ch <= '9') {
intNumberStr += ch;
cptr++;
}
else if (ch == ' ' || ch == '\t' || ch == '\n') {
cptr++;
break;
}
else {
intNumber = false;
return false;
}
}
intNumber = true;
return true;
}
else if (ch == '.') {
realNumberStr += ch;
cptr++;
ch = line[cptr];
if (ch >= '0' && ch <= '9') {
realNumberStr += ch;
cptr++;
while (cptr < (int)strlen(line)) {
ch = line[cptr];
if (ch >= '0' && ch <= '9') {
realNumberStr += ch;
cptr++;
}
else if (ch == ' ' || ch == '\t' || ch == '\n') {
cptr++;
break;
}
else {
realNumber = false;
return false;
}
}
realNumber = true;
return true;
}
}
}
else if (ch == '.') {
realNumberStr += ch;
cptr++;
ch = line[cptr];
if (ch >= '0' && ch <= '9') {
realNumberStr += ch;
cptr++;
while (cptr < (int)strlen(line)) {
ch = line[cptr];
if (ch >= '0' && ch <= '9') {
realNumberStr += ch;
cptr++;
}
else if (ch == ' ' || ch == '\t' || ch == '\n') {
cptr++;
break;
}
else {
realNumber = false;
return false;
}
}
realNumber = true;
return true;
}
else {
realNumber = false;
return false;
}
}
return false;
}
bool LineScan(
std::string wline,
bool& arithmeticOp,
bool& bracket,
bool& endOfLine,
bool& id,
bool& intNumber,
bool& logicalOp,
bool& realNumber,
bool& reservedWord,
bool& whiteSpace,
char& arithmeticOpChar,
char& bracketChar,
char& ch,
char& endOfLineChar,
char& whiteSpaceChar,
size_t& cptr,
std::string& idStr,
std::string& intNumberStr,
std::string& realNumberStr,
std::string& reservedWordStr)
{
const char* line = wline.c_str();
ch = line[cptr];
while (ch == ' ' || ch == '\t' || ch == '\n' && cptr < strlen(line)) {
cptr++;
ch = line[cptr];
}
if (ch == '\n' || cptr == strlen(line)) {
endOfLine = true;
endOfLineChar = '\n';
return true;
}
arithmeticOp = bracket = endOfLine = id = false;
intNumber = logicalOp = realNumber = whiteSpace = false;
arithmeticOpChar = '\0', bracketChar = '\0', ch = '\0';
endOfLineChar = '\0', whiteSpaceChar = '\0';
if (TokenScan(
line,
arithmeticOp,
bracket,
endOfLine,
id,
intNumber,
logicalOp,
realNumber,
reservedWord,
whiteSpace,
arithmeticOpChar,
bracketChar,
ch,
endOfLineChar,
whiteSpaceChar,
cptr,
idStr,
intNumberStr,
realNumberStr,
reservedWordStr)) {
if (id || intNumber || realNumber || reservedWord) {
return true;
}
if (endOfLine) {
return true;
}
ch = line[cptr];
if (ch == ' ' || ch == '\t' || ch == '\n') {
cptr++;
ch = line[cptr];
}
else if (ch == '\n') {
cptr++;
ch = line[cptr];
endOfLine = true;
return true;
}
}
else if (ch == '\\') {
cptr++;
if (cptr == strlen(line)) {
return false;
}
ch = line[cptr];
if (ch == '\\') {
// found a one-line comment
// skip until end-of-line
cptr++;
ch = line[cptr];
while (cptr < strlen(line) && ch != '\n') {
ch = line[cptr++];
}
return ch == '\n';
}
else {
// single \ found
return false;
}
}
const auto itao = std::find(ArithmeticOps.begin(), ArithmeticOps.end(), ch);
if (itao != ArithmeticOps.end()) {
arithmeticOp = true;
return true;
}
const auto itbc = std::find(BracketChars.begin(), BracketChars.end(), ch);
if (itbc != BracketChars.end()) {
bracketChar = true;
return true;
}
const auto itlo = std::find(LogicalOps.begin(), LogicalOps.end(), ch);
if (itlo != LogicalOps.end()) {
logicalOp = true;
return true;
}
const auto itdd = std::find(DecimalDigits.begin(), DecimalDigits.end(), ch);
if (itdd != DecimalDigits.end()) {
intNumberStr += ch;
cptr++;
ch = line[cptr];
while (ch >= '0' && ch <= '9') {
intNumberStr += ch;
}
const auto iws = std::find(WhiteSpace.begin(), WhiteSpace.end(), ch);
if (iws != WhiteSpace.end()) {
intNumber = intNumberStr.size() > 1;
whiteSpace = true;
return true;
}
else {
return false;
}
}
return false;
}
int main()
{
for (size_t i = 0; i < AlphabeticChars.size(); i++) {
AlphaNumericChars.push_back(AlphabeticChars[i]);
}
for (size_t i = 0; i < DecimalDigits.size(); i++) {
AlphaNumericChars.push_back(DecimalDigits[i]);
}
for (size_t i = 0; i < 8; i++) {
for (size_t j = 0; j < strlen(ReservedWords[i].c_str()); j++) {
reservedWordsAscii[i][j] = ReservedWords[i].c_str()[j];
}
reservedWordsAscii[i][strlen(ReservedWords[i].c_str())] = '\0';
}
const char* line0 = { };
std::string line1 = "abc4 def_5 amp c1\n";
std::string line2 = ".1234 0.4567 9876 while for\n";
std::string line3 = "\\\\this is a one-line comment\n";
std::string line4 = "a + b / c\n";
for (int i = 1; i <= 4; i++) {
bool arithmeticOp = false, bracket = false, endOfLine = false;
bool id = false, intNumber = false, logicalOp = false, realNumber = false;
bool reservedWord = false, whiteSpace = false;
char arithmeticOpChar = '\0', bracketChar = '\0', ch = '\0';
char endOfLineChar = '\0', logicalOpChar = '\0', whiteSpaceChar = '\0';
size_t cptr = 0;
std::string idStr, intNumberStr, realNumberStr, reservedWordStr;
if (i == 1) {
line0 = line1.c_str();
}
else if (i == 2) {
line0 = line2.c_str();
}
else if (i == 3) {
line0 = line3.c_str();
}
else if (i == 4) {
line0 = line4.c_str();
}
while (cptr < strlen(line0) && ch != '\n') {
if (LineScan(
line0,
arithmeticOp,
bracket,
endOfLine,
id,
intNumber,
logicalOp,
realNumber,
reservedWord,
whiteSpace,
arithmeticOpChar,
bracketChar,
ch,
endOfLineChar,
whiteSpaceChar,
cptr,
idStr,
intNumberStr,
realNumberStr,
reservedWordStr)) {
if (id) {
ch = line0[cptr];
std::cout << "id = " << idStr << std::endl;
std::cout << "cptr = " << cptr << std::endl;
std::cout << "ch = " << ch << std::endl;
id = false;
idStr = "";
}
else if (intNumber) {
std::cout << "int number = " << intNumberStr << std::endl;
std::cout << "cptr = " << cptr << std::endl;
std::cout << "ch = " << ch << std::endl;
intNumber = false;
intNumberStr = "";
}
else if (realNumber) {
std::cout << "real number = " << realNumberStr << std::endl;
std::cout << "cptr = " << cptr << std::endl;
std::cout << "ch = " << ch << std::endl;
realNumber = false;
realNumberStr = "";
}
else if (reservedWord) {
std::cout << "reserved word = " << reservedWordStr << std::endl;
std::cout << "cptr = " << cptr << std::endl;
std::cout << "ch = " << ch << std::endl;
reservedWord = false;
reservedWordStr = "";
}
else {
if (arithmeticOp) {
arithmeticOpChar = ch = line0[cptr++];
std::cout << "Arithmetic operator character = ";
std::cout << arithmeticOpChar << std::endl;
}
}
if (ch == '\0' || ch == '\n' || cptr >= strlen(line0)) {
break;
}
}
}
}
return 0;
}
Category: Computer Science
Chapter One Straight-Line Program Interpreter from “Modern Compiler Implementation in Java Second Edition” (c) 2002 by Andrew W. Appel, Translation to C++ by James Pate Williams, Jr. on Thursday, April 3, 2025
Wayback in the Spring Semester of 2006, after I was awarded my Doctor of Philosophy Degree in Computer Science, I partially audited a Compiler Design Course. Due to my mental aberrations, I was unable to complete the course. The instructor was on a Sabbatical from the United States Air Force Academy in Colorado Springs, Colorado. The textbook we used, and I still have a copy, was “Modern Compiler Implementation in Java Second Edition” © 2002 by Andrew W. Appel. Below is a translation from Java to C++ that I just completed.
// Chapter One program translated from Java to C++ by
// James Pate Williams, Jr. (c) Wednesday April 3, 2025
// Reference: "Modern Complier Implementation in Java
// Second Edition" (c) 2002 by Andrew W. Appel
#ifndef _SLPInterpreter_H
#include <iostream>
#include <stack>
#include <string>
#include <vector>
class TableEntry {
public:
std::string symbol, value;
TableEntry(std::string symbol, std::string value) {
this->symbol = symbol;
this->value = value;
}
};
std::stack<std::string> sStack;
std::vector<TableEntry> symbolTable;
class Exp {
public:
Exp() { };
virtual ~Exp() { };
};
std::stack<Exp> eStack;
class ExpList {
public:
ExpList() { };
virtual ~ExpList() { };
};
class Stm {
public:
Stm() { };
virtual ~Stm() { };
};
class CompoundStm : public Stm {
public:
Stm stm1, stm2;
CompoundStm(Stm stm1, Stm stm2) {
this->stm1 = stm1;
this->stm2 = stm2;
};
};
class AssignStm : public Stm {
public:
std::string id;
Exp exp;
AssignStm(std::string id, Exp exp) {
this->id = id;
this->exp = exp;
bool found = false;
for (int i = 0; !found && i < (int)symbolTable.size(); i++) {
if (symbolTable[i].symbol == id) {
found = true;
}
}
if (!found) {
symbolTable.push_back(TableEntry(id, ""));
}
};
void Print() {
std::cout << this->id << ' ';
};
};
class PrintStm : public Stm {
public:
ExpList exps;
PrintStm(ExpList exps) {
this->exps = exps;
};
};
class IdExp : public Exp {
public:
std::string id;
IdExp(std::string id) {
this->id = id;
Print();
TableEntry te(id, "");
};
void Print() {
std::cout << id << ' ';
};
};
class NumExp : public Exp {
public:
int num;
NumExp(int num) {
this->num = num;
Print();
char buffer[128] = { };
_itoa_s(num, buffer, 127, 10);
sStack.push(std::string(buffer));
};
void Print() {
std::cout << num << ' ';
};
};
enum class ArithmeticOp {
Plus, Minus, Times, Div
};
class OpExp : public Exp {
public:
Exp left, right;
ArithmeticOp op;
OpExp(Exp left, ArithmeticOp op, Exp right) {
this->left = left;
this->op = op;
this->right = right;
std::string ops = "";
switch (op) {
case ArithmeticOp::Plus:
ops = "+";
break;
case ArithmeticOp::Minus:
ops = "-";
break;
case ArithmeticOp::Times:
ops = "*";
break;
case ArithmeticOp::Div:
ops = "/";
break;
};
std::cout << ops << std::endl;
eStack.push(left);
eStack.push(right);
sStack.push(ops);
};
};
class EseqExp : public Exp {
public:
Stm stm; Exp exp;
EseqExp(Stm stm, Exp exp) {
this->stm = stm;
this->exp = exp;
};
};
class PairExpList : public ExpList {
public:
Exp head;
ExpList tail;
PairExpList(Exp head, ExpList tail) {
this->head = head;
this->tail = tail;
};
};
class LastExpList : public ExpList {
public:
Exp head;
LastExpList(Exp head) {
this->head = head;
};
};
#endif _SLPInterpreter_H
int main() {
int a = 0, b = 0;
Stm prog(CompoundStm(AssignStm("a",
OpExp(NumExp(5), ArithmeticOp::Plus, NumExp(3))),
CompoundStm(AssignStm("b",
EseqExp(PrintStm(PairExpList(IdExp("a"),
LastExpList(OpExp(IdExp("a"),
ArithmeticOp::Minus, NumExp(1))))),
OpExp(NumExp(10), ArithmeticOp::Times, IdExp("a")))),
PrintStm(LastExpList(IdExp("b"))))));
bool first = true;
int result = 0;
//sStack.push("0");
while (!sStack.empty()) {
std::string lts, ops, rts;
if (first) {
ops = sStack.top();
sStack.pop();
lts = sStack.top();
sStack.pop();
rts = sStack.top();
sStack.pop();
first = false;
}
else {
lts = sStack.top();
sStack.pop();
ops = sStack.top();
sStack.pop();
rts = sStack.top();
sStack.pop();
}
int lvi = std::stoi(lts);
int rvi = std::stoi(rts);
if (ops == "+") {
result = lvi + rvi;
}
else if (ops == "-") {
result = lvi - rvi;
}
else if (ops == "*") {
result = lvi * rvi;
}
else if (ops == "/") {
result = lvi / rvi;
}
char ascii[128] = { };
_itoa_s(result, ascii, 10);
if (sStack.size() != 0) {
sStack.push(std::string(ascii));
}
}
std::cout << "Result = " << result << std::endl;
return 0;
}
Approximation of the Ground-State Total Energy of a Beryllium Atom © Sunday, March 30 to Tuesday April 1, 2025, by James Pate Williams, Jr., BA, BS, Master of Software Engineering, PhD Computer Science
Blog Entry © Sunday, March 29, 2025, by James Pate Williams, Jr., BA, BS, Master of Software Engineering, PhD Slater Determinant Coefficients for Z = 2 to 4
Enter the atomic number Z (2 to 6 or 0 to quit): 2
2 1 1 + a(1)b(2)
1 0 0 - a(2)b(1)
# Even Permutations = 1
Enter the atomic number Z (2 to 6 or 0 to quit): 3
6 3 1 + a(1)b(2)c(3)
5 2 0 - a(1)b(3)c(2)
4 2 0 - a(2)b(1)c(3)
3 1 1 + a(2)b(3)c(1)
2 1 1 + a(3)b(1)c(2)
1 0 0 - a(3)b(2)c(1)
# Even Permutations = 3
Enter the atomic number Z (2 to 6 or 0 to quit): 4
24 12 0 + a(1)b(2)c(3)d(4)
23 11 1 - a(1)b(2)c(4)d(3)
22 11 1 - a(1)b(3)c(2)d(4)
21 10 0 + a(1)b(3)c(4)d(2)
20 10 0 + a(1)b(4)c(2)d(3)
19 9 1 - a(1)b(4)c(3)d(2)
18 9 1 - a(2)b(1)c(3)d(4)
17 8 0 + a(2)b(1)c(4)d(3)
16 8 0 + a(2)b(3)c(1)d(4)
15 7 1 - a(2)b(3)c(4)d(1)
14 7 1 - a(2)b(4)c(1)d(3)
13 6 0 + a(2)b(4)c(3)d(1)
12 6 0 + a(3)b(1)c(2)d(4)
11 5 1 - a(3)b(1)c(4)d(2)
10 5 1 - a(3)b(2)c(1)d(4)
9 4 0 + a(3)b(2)c(4)d(1)
8 4 0 + a(3)b(4)c(1)d(2)
7 3 1 - a(3)b(4)c(2)d(1)
6 3 1 - a(4)b(1)c(2)d(3)
5 2 0 + a(4)b(1)c(3)d(2)
4 2 0 + a(4)b(2)c(1)d(3)
3 1 1 - a(4)b(2)c(3)d(1)
2 1 1 - a(4)b(3)c(1)d(2)
1 0 0 + a(4)b(3)c(2)d(1)
# Even Permutations = 12
Enter the atomic number Z (2 to 6 or 0 to quit):
// AOPermutations.cpp : This file contains the 'main' function.
// Program execution begins and ends there.
// Copyright (c) Saturday, March 29, 2025
// by James Pate Williams, Jr., BA, BS, MSwE, PhD
// Signs of the atomic orbitals in a Slater Determinant
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
int main()
{
char alpha[] = { 'a', 'b', 'c', 'd', 'e', 'f' }, line[128] = {};
int factorial[7] = { 1, 1, 2, 6, 24, 120, 720 };
while (true)
{
int col = 0, counter = 0, row = 0, sign = 1, t = 0, Z = 0, zfact = 0;
int numberEven = 0;
std::cout << "Enter the atomic number Z (2 to 6 or 0 to quit): ";
std::cin.getline(line, 127);
std::string str(line);
Z = std::stoi(str);
if (Z == 0)
{
break;
}
if (Z < 2 || Z > 6)
{
std::cout << "Illegal Z, please try again" << std::endl;
continue;
}
zfact = factorial[Z];
std::vector<char> orb(Z);
std::vector<int> tmp(Z), vec(Z);
for (int i = 0; i < Z; i++)
{
orb[i] = alpha[i];
vec[i] = i + 1;
}
do
{
for (int i = 0; i < (int)vec.size(); i++)
{
tmp[i] = vec[i];
}
t = 0;
do
{
t++;
} while (std::next_permutation(tmp.begin(), tmp.end()));
std::cout << t << '\t' << t / 2 << '\t';
std::cout << (t / 2 & 1) << '\t';
if (Z == 2 || Z == 3)
{
if ((t / 2 & 1) == 0)
{
std::cout << "-\t";
}
else
{
std::cout << "+\t";
numberEven++;
}
}
else
{
if ((t / 2 & 1) == 1)
{
std::cout << "-\t";
}
else
{
std::cout << "+\t";
numberEven++;
}
}
for (int i = 0; i < Z; i++)
{
std::cout << orb[i] << '(' << vec[i] << ')';
}
row++;
std::cout << std::endl;
if (zfact != 2 && row == zfact)
{
std::cout << std::endl;
break;
}
row %= Z;
} while (std::next_permutation(vec.begin(), vec.end()));
std::cout << "# Even Permutations = ";
std::cout << numberEven << std::endl;
}
return 0;
}