CODEGEN.SLC is a simple parser that accepts an expression from input and writes 80x86 compatible assembly code to output. It is written in the SLC language. It is not 100% completed: you can see the beginnings of a peephole optimizer which has not yet been coded.

  1: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2: *                                                                        *
  3: * CODEGEN.SLC     Rowan Crowe <rowan#sensation'net'au>                   *
  4: *                                                                        *
  5: * Simple calculator demonstration, supports addition, subtraction,       *
  6: * multiplication, division, and bracketing.                              *
  7: *                                                                        *
  8: * This is similar to CALC.MOO supplied in COMPIxxx.ZIP downloadable via  *
  9: * http://www.rowan.sensation.net.au/slc.html , except that it doesn't    *
 10: * parse the line into an array prior to evaluating it.                   *
 11: *                                                                        *
 12: * The code could still be a lot neater by not relying on using global    *
 13: * variables across several functions.                                    *
 14: *                                                                        *
 15: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 16: 
 17: extern int itostr()
 18: extern int strtoui()
 19: extern int input()
 20: extern int puts()
 21: extern int putc()
 22: extern int isdigit()
 23: extern int isalpha()
 24: extern int tinymeminit()
 25: extern int malloc()
 26: extern int free()
 27: extern void abort()
 28: extern int neg()
 29: 
 30: define REG_AX       0
 31: define REG_BX       1
 32: 
 33: define OP_PUSHREG   0
 34: define OP_POPREG    1
 35: define OP_ADDREG    2
 36: define OP_SUBREG    3
 37: define OP_DIVREG    4
 38: define OP_MULREG    5
 39: 
 40: global int errno
 41: global char *p
 42: global int errorflag
 43: global int locallabel
 44: 
 45: int evaluate () {
 46:   compare()
 47: }
 48: 
 49: int compare () {
 50:   int t
 51:   add_subtract()
 52:   while ((*p != 0) && ((*p == '=' && *(p+1) == '=') || (*p == '<') || (*p == '>'))) {
 53:     if (*p == '<') {
 54:       p = p + 1
 55:       puts("\tpush\tax\n")
 56:       add_subtract()
 57:       puts("\tpop\tbx\n\tcmp\tax,bx\n\tmov\tax,-1\n")
 58:       t = locallabel
 59:       locallabel = locallabel + 1
 60:       puts("\tjl\tLL")
 61:       puts(itostr("1234567", locallabel))
 62:       puts("\n\tinc\tax\nLL")
 63:       puts(itostr("1234567", locallabel))
 64:       puts(":\n")
 65:     }
 66:     if (*p == '>') {
 67:       p = p + 1
 68:       puts("\tpush\tax\n")
 69:       add_subtract()
 70:       puts("\tpop\tbx\n\tcmp\tax,bx\n\tmov\tax,-1\n")
 71:       t = locallabel
 72:       locallabel = locallabel + 1
 73:       puts("\tjg\tLL")
 74:       puts(itostr("1234567", locallabel))
 75:       puts("\n\tinc\tax\nLL")
 76:       puts(itostr("1234567", locallabel))
 77:       puts(":\n")
 78:     }
 79:   }
 80: }
 81: 
 82: int add_subtract() {
 83:   divide_multiply()
 84:   while ((*p != 0) && ((*p == '+') || (*p == '-'))) {
 85:     if (*p == '+') {
 86:       p = p + 1
 87:       puts("\tpush\tax\n")
 88:       divide_multiply()
 89:       puts("\tpop\tbx\n\tadd\tax,bx\n")
 90:     }
 91:     if (*p == '-') {
 92:       p = p + 1
 93:       puts("\tpush\tax\n")
 94:       divide_multiply()
 95:       puts("\tmov\tbx,ax\n\tpop\tax\n\tsub\tax,bx\n")
 96:     }
 97:   }
 98: }
 99: 
100: int divide_multiply() {
101:   bracket()
102:   while ( (*p != 0) && ( (*p == '/') || (*p == '*') ) ) {
103:     if (*p == '/') {
104:       p = p + 1
105:       puts("\tpush\tax\n")
106:       bracket()
107:       puts("\tmov\tbx,ax\n\tpop\tax\n\tdiv\tbx\n")
108:     }
109:     if (*p == '*') {
110:       p = p + 1
111:       puts("\tpush\tax\n")
112:       bracket()
113:       puts("\tmov\tbx,ax\n\tpop\tax\n\tmul\tbx\n")
114:     }
115:   }
116: }
117: 
118: int bracket() {
119:   int rv
120: 
121:   remove_whitespace()
122: 
123:   if (isdigit(*p) || isalpha(*p)) {
124:     fetchname()
125:     return
126:   }
127:   switch(*p) {
128:     case '(' {
129:       p = p + 1
130:       rv = add_subtract()
131:       if (*p != ')') {
132:         puts("syntax error: expected ')' closing bracket\n")
133:         errorflag = 1
134:         return 0
135:       } else {
136:         p = p + 1
137:         remove_whitespace()
138:         return rv
139:       }
140:     }
141:     case '-' {
142:       p = p + 1
143:       if (isdigit(*p)) {
144:         puts("-")
145:         puts(fetchname())
146:       }
147:     }
148:     case else {
149:       puts("syntax error: unexpected token '")
150:       putc(*p)
151:       puts("'\n")
152:       *p = '0'
153:       errorflag = 1
154:       return 0
155:     }
156:   }
157: }
158: 
159: int fetchname() {
160:   puts("\tmov\tax,")
161:   while ((isdigit(*p) || isalpha(*p)) && *p != 0) {
162:     putc(*p)
163:     p = p + 1
164:   }
165:   puts("\n")
166:   remove_whitespace()
167: }
168: int fetchnumber() {
169:   char *tmpbuf
170:   char *d
171: 
172:   if ((tmpbuf = malloc(20)) == -1) {
173:     puts("memory allocation failed.\n")
174:     abort(0)
175:   }
176: 
177:   d = tmpbuf
178:   while (isdigit(*p) && *p != 0) {
179:     *d = *p
180:     p = p + 1
181:     d = d + 1
182:   }
183:   *d = 0
184:   remove_whitespace()
185:   free(tmpbuf)
186:   puts(strtoui(tmpbuf))
187: }
188: 
189: void remove_whitespace() {
190:   while (*p == ' ') {
191:     p = p + 1
192:   }
193: }
194: 
195: void add_peep(int opcode, int parm1, int parm2) {
196: }
197: 
198: int main() {
199:   int rv
200:   char *origp
201:   int exitnow
202: 
203:   if ((rv = tinymeminit(4096)) == -1) {
204:     puts("memory init failed.\n")
205:     abort(0)
206:   }
207:   if ((p = malloc(51)) == -1) {
208:     puts("memory allocation failed.\n")
209:     abort(0)
210:   }
211:   origp = p
212: 
213:   exitnow = 0
214:   locallabel = 0
215:   while (exitnow == 0) {
216:     p = origp
217:     errorflag = 0
218:     puts("> ")
219:     rv = input(p, 50)
220:     puts("\n; ")
221:     puts(p)
222:     puts("\n")
223:     if (*p != 0) {
224:       rv = evaluate()
225:       if (errorflag == 0) {
226:         puts("\n")
227:       }
228:     } else {
229:       exitnow = 1
230:     }
231:   }
232:   puts("\nBye!\n")
233:   free(p)  /* ignore return value */
234:   return 0
235: }
236: 
237: 



Return to SLC homepage