int Scanner::GetToken(int *sub) { *sub = 0; skip_non_token(); // char c = cur_char(); if (is_dec(c)) { return read_num(); } // struct OperatorTableEntry *op = lookup_op(); if (op) { int r; r = read_op(op); *sub = op->sub_op; return r; } // if (c == '\"') { return read_str(); } if (is_symhead(c)) { return read_sym(); } return -1; }
atom_t* read_atom(scanner_t *scan){ slice_t slice; int c = scan_while_func(scan, NULL, isspace); while (c == ';'){ scan_until(scan, NULL, '\n'); c = scan_peek(scan); } if (c == EOF) { return nil_atom(); } else if (c == '(') { return read_list(scan); } else if (c == '\'') { // Quote scan_one_of(scan, '\''); atom_t *content = read_atom(scan); return pair_atom_alloc(sym_atom_alloc("quote"), pair_atom_alloc(content, nil_atom())); } else if (c == '"') { // String scan_one_of(scan, '"'); scan_until(scan, &slice, '"'); return str_atom_alloc(slice.ptr); } else if ( isdigit(c) ) { // Number scan_while_func(scan, &slice, isdigit); int64_t value = strtoll(slice.ptr, NULL, 10); free(slice.ptr); return num_atom_alloc(value); } else { return read_sym(scan); } }
int dothehardpart( void ) { int len, c, n=0; int faux_pas= 0; long codesize= 0; /* initialize globals */ numsyms= numlines= 0; /* begin scanning the input stream */ c= fgetc(fin); if(c != 0xf5) { warn("Hmmm... this doesn't look like an AmigaBASIC binary.\n" "My output will probably look a bit funny. Proceed, for a laugh."); } if( feof(fin) || ferror(fin) ) { warn("unexpected end of input -- no code, no symbols"); return 1; } /* read the code segment */ do { /* Stefan Reisner thought that AmigaBASIC encodes the length of a line * in a 2 byte word prefix. This is not the whole truth... * I've experienced that the first byte holds a flag (e.g. 0x80 indicates * a line number) and only the second byte encodes the length. */ c= fgetc(fin); /* flags */ if( len= fgetc(fin) ) { codesize += len; len-= 2; if( !feof(fin) && !ferror(fin) ) n= read_line(fin,len,c); } } while( len && n == len && !ferror(fin) && !feof(fin) ); if( len ) { if( n != len || ferror(fin) ) { warn("I'm confused; after having read the code segment, I still seem\n" "to want to go on. In fact I just wanted to read another %d bytes\n" "when a serious problem interrupted me. I'll try to forget about this.",len); } if( feof(fin) ) { warn("Uh, oh. I suspect there was a null missing at the end of the code segment,\n" "causing me to read past where I should stop.\n" "I'll forget about the symbols now. Proceed, with fingers crossed."); } } else if( feof(fin) || ferror(fin) ) /* and len <= 0 */ warn("This seems to be a funny program. The input ended without any symbol definitions.\n"); /* read the symbols */ if( !ferror(fin) && !feof(fin) ) { int ok= 1; #ifdef DEBUG if(debuglevel >= 1) fprintf(stderr,"skipping a '\\x%02x' character\n",fgetc(fin)); else #endif (void)fgetc(fin); /* skip null byte */ if( (codesize & 1) == 0 ) { #ifdef DEBUG if(debuglevel >= 1) fprintf(stderr,"skipping another '\\x%02x' character\n",fgetc(fin)); else #endif (void)fgetc(fin); } if( feof(fin) || ferror(fin) ) { warn("I was just about to read the symbols when I reached the end of file.\n" "Maybe we have a BASIC program without symbols? We'll see..."); } else do { len= fgetc(fin); if( !feof(fin) ) ok= read_sym(fin, len, numsyms++); } while( ok && !feof(fin) && !ferror(fin) ); if( !ok ) { warn("After having read %ld %s I couldn't get another %d bytes.\n" "Maybe there is not enough free store? I'll better stop reading symbols!", numsyms-1, (numsyms-1 == 1) ? "symbol": "symbols"); } } #ifdef DEBUG if(debuglevel >= 1) fprintf(stderr,"expanding %ld lines of code w/ %d symbols\n",numlines,numsyms); #endif expand_code(); /* we _must_ call these to become re-entrant */ free_symbols(); free_code(); return faux_pas; }
Grammar* load_grammar(FILE* file, Grammar* g) { enum States current_state = START; // Stato iniziale //enum States error = -1; Symbol s; Production* p = NULL; Errors error; error.size = 0; if(file != stdin) g->numprod = 0; // Inizializza la grammatica while ( !feof(file) ) { s = read_sym(file); switch (current_state) { case START: if (is_terminal(s) || is_nonterminal(s)) { current_state = LEFT; //p = &(g->productions[g->numprod++]); //p->left.length = 0; p = add_new_production(g); add_symbol(&p->left, s); //L'istruzione precedente corrisponde a p->left.word[p->left.length++] = s; } else if (is_prodsep(s)) { current_state = START; } else if (ispunct(s) || isgraph(s)) { current_state = LEFT; p = add_new_production(g); add_symbol(&p->left, s); error.type[error.size] = INVALID_SYMBOL; error.lines[error.size] = g->numprod; error.size++; } break; case LEFT: if (is_terminal(s) || is_nonterminal(s)) { current_state = LEFT; add_symbol(&p->left, s); } else if (is_prodsym(s)) { current_state = RIGHT; //ErrorManager(NO_NT, p); } else if (ispunct(s) || isgraph(s)) { current_state = LEFT; add_symbol(&p->left, s); error.type[error.size] = INVALID_SYMBOL; error.lines[error.size] = g->numprod; error.size++; } else if(is_prodsep(s) || s == EOF) { error.type[error.size] = NO_PRODSYM; error.lines[error.size] = g->numprod; error.size++; //ErrorManager(NO_PRODSYM_MAYBE, p, g->numprod); current_state = START; if (!CheckNonTerminal(p)) { error.type[error.size] = NO_NT; error.lines[error.size] = g->numprod; error.size++; } } else { error.type[error.size] = NO_PRODSYM; error.lines[error.size] = g->numprod; error.size++; current_state = RIGHT; } break; case RIGHT: if (is_terminal(s) || is_nonterminal(s)) { current_state = RIGHT; add_symbol(&p->right, s); } else if (is_prodsep(s) || s == EOF) { current_state = START; g->productions[g->numprod-1].left.word[g->productions[g->numprod-1].left.length] = '\0'; g->productions[g->numprod - 1].right.word[g->productions[g->numprod - 1].right.length] = '\0'; //ErrorManager(error, p,g->numprod); } else if (ispunct(s) || isgraph(s)) { current_state = RIGHT; add_symbol(&p->right, s); error.type[error.size] = INVALID_SYMBOL; error.lines[error.size] = g->numprod; error.size++; } break; } } if (error.size > 0) { DrawErrors(error, g); if (!CheckInitSymbol(g)) ErrorManager(NO_INITSYM, NULL, 0); g = NULL; } if (g) if (!CheckInitSymbol(g)) { ErrorManager(NO_INITSYM, NULL,0); g = NULL; } return g; }
Grammar* load_grammar(FILE* file, Grammar* g){ enum States {START,LEFT,RIGHT,ERROR}; /* START = Scansione di una nuova produzione [F] LEFT = Scansione della parte sinistra RIGHT = Scansione della parte destra [F] ERROR = Errore di scansione */ enum States current_state = START; // Stato iniziale Symbol s; Production* p; int contatore=0; while ( !feof(file)) { s = read_sym(file); if (feof(file)) break; switch(current_state){ case START: if (is_terminal(s) || is_nonterminal(s)||is_prodsym(s)){ current_state = LEFT; p = add_new_production(g); if (is_prodsym(s)){ current_state = RIGHT; p->error=4; add_symbol(&p->left,' '); } else add_symbol(&p->left,s); } else if (is_prodsep(s)){ current_state = START; } else { current_state = LEFT; add_symbol(&p->left,s); p->error=3; } break; case LEFT: if (is_terminal(s) || is_nonterminal(s)){ current_state = LEFT; add_symbol(&p->left,s); } else if (is_prodsym(s)){ current_state = RIGHT; } else{ if(is_prodsep(s)){ p->error=1; current_state=START; } else{ current_state = LEFT; add_symbol(&p->left,s); p->error=3; } } break; case RIGHT: if (is_terminal(s) || is_nonterminal(s)){ current_state = RIGHT; add_symbol(&p->right,s); } else if(is_prodsep(s)){ current_state = START; } else{ current_state = RIGHT; p->error=2; add_symbol(&p->right,s); } break; } } return g; }