2011-03-30 2 views
5

Je travaille sur un shell, un petit shell de type bash, sans script (si tout le temps ...) Je dois faire le lexer/parser (LL) par main.Comment écrire un lexer (shell) à la main

Ainsi, le lexer transformera la commande (char * cmd) à une liste chaînée (t_list * Liste). Et l'analyseur LL transformera la liste chaînée (de t_list * Liste) à un AST (arbre binaire t_btree * racine) avec un So grammar

, je sais comment faire l'analyseur LL mais je n » Je sais comment symboliser ma commande.

Par exemple: ps | grep ls >> file ; make && ./a.out

=>'ps' '|' 'grep' 'ls' '>>' 'file' ';' ''make '&&' './a.out'

Merci.

(Je ne veux pas utiliser tout générateur)

+1

qu'est-ce que vous avez à ce jour? où es-tu coincé? – Mat

+1

Depuis que vous l'avez marqué comme 'C simple', il semble que vous devriez viser une boucle sur la chaîne de commande en utilisant des appels répétés à 'strchr (cmd, '')' ou quelque chose de cette nature. – phooji

+1

'switch/case' machine à états? – Spudd86

Répondre

6

(Ceci explique l'idée par laissé entrevoir Spudd86).

Vous devez implémenter une machine à états finis. Il y a les états suivants:

  • Etat général
  • l'intérieur d'un nom de fichier
  • A l'intérieur du && jeton
  • A l'intérieur du || jeton

Pour chaque état et le caractère d'entrée suivante, vous avoir à décider quel est l'état suivant, et s'il faut sortir un jeton.Par exemple:

  • État actuel: Général; Caractère: x => état suivant: l'intérieur-file-name
  • état actuel: l'intérieur-file-name; caractère: espace => état suivant: Général; affiche le jeton
  • État actuel: nom de fichier interne; caractère: & => état suivant: inside- & &; émettre le jeton
  • Etat actuel: inside- & &; caractère: & => état suivant: Général; émettre le jeton
  • Etat actuel: inside- & &; caractère: x => état suivant: Général; erreur de syntaxe
  • ... (ad nauseam)

Il est beaucoup de travail ennuyeux de travailler toutes les règles (le plaisir commence lorsque vous devez déboguer le code résultant), de sorte que la plupart des gens utilisent des générateurs de code pour le faire .


Edit: un code (désolé si la syntaxe est décoiffé; i habituellement programme en C++)

enum state { 
    STATE_GENERAL, 
    STATE_IN_FILENAME, 
    ... 
}; 

// Many characters are treated the same (e.g. 'x' and 'y') - so use categories 
enum character_category 
{ 
    CHAR_GENERAL, // can appear in filenames 
    CHAR_WHITESPACE = ' ', 
    CHAR_AMPERSAND = '&', 
    CHAR_PIPE = '|', 
    CHAR_EOF = EOF, 
    ... 
}; 

character_category translate(int c) 
{ 
    switch (c) { 
    case '&': return CHAR_AMPERSAND; 
    case ' ': case '\t': case '\n': return CHAR_WHITESPACE; 
    ... 
    default: return CHAR_GENERAL; 
    } 
} 

void do_stuff() 
{ 
    character_category cat; 
    state current_state = STATE_GENERAL; 
    state next_state; 
    char token[100]; 
    char token_length = 0; 
    do { 
     int c = getchar(); 
     cat = translate(c); 
     // The following implements a switch on 2 variables 
     int selector = 1000 * current_state + cat; 

     switch (selector) 
     { 
     case 1000 * STATE_GENERAL + CHAR_GENERAL: 
      next_state = STATE_IN_FILENAME; 
      token[token_length++] = c; // append a character to a filename token 
      break; 

     case 1000 * STATE_GENERAL + CHAR_WHITESPACE: 
      next_state = STATE_GENERAL; // do nothing 
      break; 

     case 1000 * STATE_GENERAL + CHAR_PIPE: 
      next_state = STATE_IN_OR_TOKEN; // the first char in '||' or just '|' 
      break; 

     // Much repetitive code already; define a macro for the case constants? 
     // Have to cover all states and all character categories; good luck... 

     case 1000 * STATE_IN_FILENAME + EOF: 
     case 1000 * STATE_IN_FILENAME + CHAR_WHITESPACE: 
      next_state = STATE_GENERAL; 
      printf("Filename token: %s\n", token); 
      break; 

     default: 
      printf("Bug\n"); // forgot one of the cases? 
     } 

     current_state = next_state; 

    } while (cat != CHAR_EOF); 
} 
+0

Merci. J'ai vu des choses à propos de la "machine à états finis" mais cela vous dérangerait-il de me donner un exemple concret? Je veux dire un petit exemple "C". Je ne sais pas quoi faire avec onglet/espace et .. Etc – mathieug

Questions connexes