2016-05-26 20 views
0

Parsen Ich möchte str="HELLO" folgendes Skripteine bedingte mit Zitrone

str="HELLO" 
if [ $str = "HELLO" ]; then 
    echo FOO 
fi 

Die erste Zeile analysieren ich analysieren kann und die Variable wird für die Nutzung gespeichert. Es ist möglich, das Skript

str="HELLO" 
echo $str 

und erhalten die Ausgabe HELLO zu laufen.

Aber ich kann noch nicht die bedingte if-Anweisung tun. Also frage ich mich, wie ich mit der bedingten Aussage verfahren soll. Ich habe versucht, die Definition dieser Zitrone Grammatik

expr(A) ::= IF '[' expr(B) EQEQ expr(C) '];then' expr(C) 'fi'.

Aber es gibt mir eine Fehlermeldung, dass das Zitat illegal char ist. Ich weiß also nicht, wie ich die Grammatik für die if-Anweisung schreiben soll. Mein ganzer grammar ist

%include 
{ 
#include "types.h" 
#include "openshell.h" 
#include "assert.h" 
} 
%syntax_error { fprintf(stderr, "Syntax error\n"); } 
%token_type { struct SToken* } 
%type expr { int } 

%nonassoc EQEQ NOTEQ SET LARGER SMALLER. 
%left FOR WHILE IF. 
%left PLUS MINUS. 
%left TIMES DIVIDE. 

program ::= expr(A). { setresult(A); /*printf("%d\n", A);*/ } 
expr(A) ::= expr(B) PLUS expr(C). {A = B + C; } 
expr(A) ::= expr(B) MINUS expr(C). {A = B - C; } 
expr(A) ::= expr(B) TIMES expr(C). {A = B * C; } 
expr(A) ::= expr(B) EQEQ expr(C). {if(B==C) {A=1;} else A=0;} 
expr(A) ::= expr(B) NOTEQ expr(C). {if(B==C) {A=0;} else A=1;} 
expr(A) ::= expr(B) LARGER expr(C). {if(B>C) {A=1;} else A=0;} 
expr(A) ::= expr(B) SMALLER expr(C). {if(B<C) {A=1;} else A=0;} 

expr(A) ::= expr(B) SET expr(C). {A=C;B=C;} 


expr(A) ::= IF '[' expr(B) EQEQ expr(C) '];then' expr(C) 'fi'. 


expr(A) ::= FOR LPAR expr(B) SEMICOLON expr(C) SEMICOLON expr(D) RPAR expr(E). {A = D*B*E*C+1; } /* $((for (1 == 1 ; 2 == 2 ; 3 == 3) 55)) */ 
expr(A) ::= WHILE LPAR expr(B) RPAR expr(C). 
{ 
while (B) { printf("%d", C); 
} 
A=C;printf("\n"); 
} 
expr(A) ::= expr(B) DIVIDE expr(C). 
{ 
    if (C != 0) 
    { 
     A = B/C; 
    } 
    else 
    { 
     fprintf(stderr, "divide by 0"); 
    } 
} 
expr(A) ::= LPAR expr(B) RPAR. { A = B; } 
expr(A) ::= INTEGER(B). 
{ 
//printf("the result = %s\n", B->token); 
    A = B->value; 
    //printf("Passed argument: %s\n", B->token); 
} 

Meine main Schleife wie folgt aussieht.

int main(int argc, char *argv[]) { 
    bool donotrun = false; 
    struct sigaction new_action, old_action; 
    hashtable_t *hashtable = ht_create(65536); 
    /* Set up the structure to specify the new action. */ 
    new_action.sa_handler = termination_handler; 
    sigemptyset(&new_action.sa_mask); 
    new_action.sa_flags = 0; 

    sigaction(SIGINT, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
     sigaction(SIGINT, &new_action, NULL); 
    sigaction(SIGHUP, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
     sigaction(SIGHUP, &new_action, NULL); 
    sigaction(SIGTERM, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
     sigaction(SIGTERM, &new_action, NULL); 

    int value; 
    void *pParser; 
    char *c; 
    // struct SToken v[argc]; 

    int index = 0; 
    int i; 
    char *cvalue = NULL; 
    const char *commandFile; 
    bool quietFlag; 

    while (1) { 
     index = 0; 
     i = getopt_long(argc, argv, "pc:vh", 
         options, &index); 
     if (i == -1) 
      break; 
     switch (i) { 
      case 'p': { 
       exit(EXIT_SUCCESS); 
      } 
      case 'v': { 
       printf("sh OpenShell version 0.1(a)\n"); 
       printf("Version: %s\n", VERSION); 
       exit(EXIT_SUCCESS); 

      } 
      case 'h': { 
       usage(); 
       exit(EXIT_SUCCESS); 

      } 
      case 'c': { 
       cvalue = optarg; 
       command(cvalue, hashtable); 
       exit(EXIT_SUCCESS); 
      } 

      case 'f': 
       /* 
       * Execute commands from file. 
       * This is used for osh script files. 
       * The quiet flag is also set. 
       */ 
       if ((argc != 1) || commandFile) 
        usage(); 

       quietFlag = true; 
       argc--; 

       break; 


      case '?': 
       if (optopt == 'c') 
        fprintf(stderr, "Option -%c requires an argument.\n", optopt); 
       else if (isprint (optopt)) 
        fprintf(stderr, "Unknown option `-%c'.\n", optopt); 
       else 
        fprintf(stderr, 
          "Unknown option character `\\x%x'.\n", 
          optopt); 
      default: { 
       return 1; 
      } 
     } 
    } 
    getPath(); 
    pParser = (void *) ParseAlloc(malloc); 
    char *copy; 

    for (; ;) { 
     bool scanning = true; 
     bool calc = true; 
     while (scanning) { 
      char *line = NULL; 
      line = readline("$ "); 
      //return 0; 
      if (line) 
       copy = strdup(line); 

      if (line && strstr(line, "=")) { 
       donotrun = true; 
       char str[128]; 
       char *ptr; 
       strcpy(str, line); 
       strtok_r (str, "=", &ptr); 
       ht_set(hashtable, str, ptr); 
      } 

      if (!scanning) 
       break; 

      if (!isatty(fileno(stdin))) { 
       *argv++; 
       readFile(*argv++, hashtable); 
       free(line); 
       exit(0); 
      } 
      else { 

       if (!donotrun) { 
        command(line, hashtable); 
       } 
       donotrun = false; 
       add_history(copy); 

      } 
      free(copy); 
     } 
    } 
    return 0; 
} 

Das Problem ist, dass ich weiß nicht, wie die eckige Klammer für die if-Anweisung in der Grammatik zu erklären. Eine if-Anweisung ist afaik eine "zusammengesetzte" Anweisung der Bedingung und der auszuwertende Ausdruck, wenn die Bedingung wahr ist, also werden mindestens 2 oder 3 Ausdrücke beteiligt sein. Ich habe bereits definierte Gleichheit Ausdruck, das funktioniert:

expr(A) ::= expr(B) EQEQ expr(C). {if(B==C) {A=1;} else A=0;}

Aber ich bekomme einen Compiler-Fehler von Zitrone, wenn ich versuche, die eckigen Klammern in Anführungszeichen zu machen, und wenn ich Anführungszeichen nicht dann verwende ich einen Einen Fehler:

Illegal character on RHS of rule: "[".

Der obige Fehler, wenn ich versuche, und erklären:

expr(A) ::= IF [ expr(B) EQEQ expr(C) ];then expr(C) 'fi'.

Antwort

1

Nach the documentation:

Yacc and bison allow terminal symbols to have either alphanumeric names or to be individual characters included in single quotes, like this: ')' or '$'. Lemon does not allow this alternative form for terminal symbols. With Lemon, all symbols, terminals and nonterminals, must have alphanumeric names.