Re: Generating a simple hand-coded like recursive descent parser

Tommy Thorn <tommy.thorn@gmail.com>
12 Sep 2006 18:58:42 -0400

          From comp.compilers

Related articles
[11 earlier articles]
Re: Generating a simple hand-coded like recursive descent parser ArarghMail609@Arargh.com (2006-09-11)
Re: Generating a simple hand-coded like recursive descent parser DrDiettrich1@aol.com (Hans-Peter Diettrich) (2006-09-11)
Re: Generating a simple hand-coded like recursive descent parser mailbox@dmitry-kazakov.de (Dmitry A. Kazakov) (2006-09-11)
Re: Generating a simple hand-coded like recursive descent parser mr.waverlye@verizon.net (Mr.E) (2006-09-11)
Re: Generating a simple hand-coded like recursive descent parser ArarghMail609@Arargh.com (2006-09-11)
Re: Generating a simple hand-coded like recursive descent parser mr.waverlye@verizon.net (Mr.E) (2006-09-11)
Re: Generating a simple hand-coded like recursive descent parser tommy.thorn@gmail.com (Tommy Thorn) (2006-09-12)
Re: Generating a simple hand-coded like recursive descent parser mr.waverlye@verizon.net (Mr.E) (2006-09-16)
Re: Generating a simple hand-coded like recursive descent parser tommy.thorn@gmail.com (Tommy Thorn) (2006-09-18)
The 30 min optimizing native code compiler [was: Generating a simple h tommy.thorn@gmail.com (Tommy Thorn) (2006-09-21)
Re: Generating a simple hand-coded like recursive descent parser DrDiettrich1@aol.com (Hans-Peter Diettrich) (2006-09-21)
Re: Generating a simple hand-coded like recursive descent parser chris.dollin@hp.com (Chris Dollin) (2006-09-22)
Re: Generating a simple hand-coded like recursive descent parser DrDiettrich1@aol.com (Hans-Peter Diettrich) (2006-09-25)
[29 later articles]
| List of all articles for this month |

From: Tommy Thorn <tommy.thorn@gmail.com>
Newsgroups: comp.compilers
Date: 12 Sep 2006 18:58:42 -0400
Organization: Sonic.Net
References: 06-09-02906-09-039 06-09-042 06-09-048
Keywords: parse, Basic

Mr.E wrote:
> ... our fathers BASIC is different from todays BASIC.


Ah, I show my age again :-)


> I will study your example and make good use of it.
>
> Thank you very much for your input.


I'll readily admit I had much fun hacking it together, though I hope
you realize that this is not production ready code and the style is
aweful (to make it fit).


Our dear moderator be willing, I've made it a tad more realistic and
finish the 2nd half: a JIT binary code compiler (works on x86 Linux in
32-bit mode).


Do feel free to ask questions.


Enjoy,
Tommy


#include <ctype.h>
#include <stdio.h>


char *s;
int lookahead;
int intValue;
char *symbolValue;
unsigned symbolLength;


void nexttoken(void) {
                  while (isspace(*s)) ++s;
                  if (isdigit(*s)) {
                                  intValue = 0;
                                  lookahead = '0';
                                  while (isdigit(*s)) intValue = 10*intValue + *s++ - '0';
                  } else if (isalpha(*s)) {
                                  lookahead = 'a';
                                  symbolValue = s;
                                  while (isalnum(*s)) ++s;
                                  symbolLength = symbolValue - s;
                  } else lookahead = *s++; }
void match(unsigned expect) {
                  if (lookahead != expect) lookahead = -1;
                  nexttoken(); }


typedef struct node *ast_t;
struct node {
                  int kind;
                  ast_t l, r;
                  int intValue;
} nodes[9999];
int next = 0;
ast_t mk(int kind, ast_t l, ast_t r, int k) {
                  nodes[next].kind = kind;
                  nodes[next].l = l;
                  nodes[next].r = r;
                  nodes[next].intValue = k;
                  return &nodes[next++]; }


ast_t pExp(void);
ast_t pFactor(void) {
                  ast_t v;
                  switch (lookahead) {
                  case '(': match('('); v = pExp(); match(')'); break;
                  case 'a': v = mk('a', 0,0, symbolValue[0]); match('a'); break;
                  case '0': v = mk('0', 0,0, intValue); match('0'); break; }
                  return v;}
ast_t pTerm(void) {
                  ast_t v = pFactor();
                  while (lookahead == '*') match('*'),v=mk('*',v,pFactor(),0);
                  return v;}
ast_t pExp(void) {
                  ast_t v = pTerm();
                  while (lookahead == '+') match('+'),v=mk('+',v,pTerm(),0);
                  return v;}


void prast(ast_t t) {
                  if (t->kind == '0') printf("%d", t->intValue);
                  else if (t->kind == 'a') printf("%c", t->intValue);
                  else { printf("(");
                  prast(t->l); printf("%c", t->kind); prast(t->r); printf(")");}}


char code[9999], *cp = code;
int env[256] = { ['x'] = 2, ['y'] = 3 };


void gen(ast_t t) {
                  if (t->kind == '0') {
                                  *cp++ = 0x50; // push %eax
                                  *cp++ = 0xB8; // movl $<intValue>, %eax
                                  *(int *)cp = t->intValue;
                                  cp += 4;
                  } else if (t->kind == 'a') {
                                  *cp++ = 0x50; // push %eax
                                  *cp++ = 0xA1; // mov <env[..]>, %eax
                                  *(int **)cp = &env[t->intValue];
                                  cp += 4;
                  } else {
                                  gen(t->r);
                                  gen(t->l);
                                  *cp++ = 0x5B; // pop %ebx
                                  if (t->kind == '+') *cp++=1, *cp++=0xD8; // add %ebx,%eax
                                  else *cp++=0xF, *cp++=0xAF, *cp++=0xC3; // imul %ebx, %eax
}}


int main(int argc, char **argv) {
                  ast_t res;
                  s = "1 + x*3 + 4*(5 + y)";
                  if (argc > 1) s = argv[1];
                  nexttoken();
                  res = pExp();
                  if (lookahead != 0){printf("Syntax error at:%s\n", s); return -1;}
                  prast(res);
                  printf("\n");


                  gen(res);
                  *cp++=0x5B; // pop dummy
                  *cp++=0xC3; // ret
                  printf("%d\n", ((int(*)()) code)());
                  return 0;
}


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.