Frage

Mit der folgenden Grammatik, bekomme ich einen Syntaxfehler mit dieser Art von Eingabe:

ls /home > foo #Runs and works okay, but raises error token
ls /home /foo /bar /etc #works okay

Ich denke, es hat etwas mit, wie Look-Ahead-Werke zu tun hat, aber dies ist meine erste Grammatik und ich bin ein wenig verwirrt darüber, warum es nicht auf diese Weise nicht: external_cmd GT WORD eine Umleitung ist, umleiten ist ein Befehl, Befehl ist ein Befehl, so Eingabebefehle NEWLINE funktionieren soll.

Top Regeln der Grammatik:

input:
    error NEWLINE {
        printf("Error Triggered\n");
        yyclearin;
        yyerrok; 
        prompt(); 
    } |
    input NEWLINE {
        prompt();
    } | 
    input commands NEWLINE {
        prompt (); 
    } | 
    /* empty */
    ;   

commands: 
    command |   
    command SEMI | 
    command SEMI commands
    ;   

command:
    builtin_cmd |
    redirect |
    external_cmd { 
        execute_command($1, 0, NULL);
    }
    ;

redirect:
    external_cmd GT WORD  {
        printf("Redirecting stdout of %s to %s\n", $1->cmd, $3);
        //printf("DEBUG: GT\n");
        execute_command($1, STDOUT_FILENO, $3);
    }
    external_cmd LT WORD {
        printf("Redirecting stin of %s to %s\n", $1->cmd, $3);
        //printf("DEBUG: GT\n");
        execute_command($1, STDIN_FILENO, $3);
    }
    ;

Die Debug / ausführlicher Eingang, wenn die Fehler-Token erhöht:

Next token is token WORD ()
Shifting token WORD ()
Entering state 6
Reading a token: Next token is token WORD ()
Shifting token WORD ()
Entering state 24
Reading a token: Next token is token GT ()
Reducing stack by rule 22 (line 115):
   $1 = token WORD ()
-> $$ = nterm arg_list ()
Stack now 0 2 6
Entering state 26
Reducing stack by rule 19 (line 91):
   $1 = token WORD ()
   $2 = nterm arg_list ()
-> $$ = nterm external_cmd ()
Stack now 0 2
Entering state 16
Next token is token GT ()
Shifting token GT ()
Entering state 29
Reading a token: Next token is token WORD ()
Shifting token WORD ()
Entering state 33
Reducing stack by rule 11 (line 68):
Redirecting stdout of ls to foo
DEBUG: redirect mode is 1
DEBUG: Command to run is ls
DEBUG: Adding Argument /home
admin  kbrandt  tempuser
-> $$ = nterm @1 ()
Stack now 0 2 16 29 33
Entering state 34
Reading a token: Next token is token NEWLINE ()
syntax error
Error: popping nterm @1 ()
Stack now 0 2 16 29 33
Error: popping token WORD ()
Stack now 0 2 16 29
Error: popping token GT ()
Stack now 0 2 16
Error: popping nterm external_cmd ()
Stack now 0 2
Error: popping nterm input ()
Stack now 0
Shifting token error ()
Entering state 1
Next token is token NEWLINE ()
Shifting token NEWLINE ()
Entering state 3
Reducing stack by rule 1 (line 38):
   $1 = token error ()
   $2 = token NEWLINE ()
Error Triggered
-> $$ = nterm input ()
Stack now 0
Entering state 2

Update:
external_cmd ist:

external_cmd:
    WORD arg_list {
        $$ = malloc( sizeof(struct ext_cmd) );
        if ( $$ == NULL)
            printf("Memory Allocation Error\n");
        $$->cmd = $1;
        $$->args_pp = $2;
    } |
    WORD    {
        $$ = malloc( sizeof(struct ext_cmd) );
        if ( $$ == NULL)
            printf("Memory Allocation Error\n");
        $$->cmd = $<string>1;
        $$->args_pp = NULL;
    }
War es hilfreich?

Lösung 3

Gefunden es, in meiner Umleitung Regel gibt es eine fehlende Rohr, so dass anstelle von zwei Komponenten, gibt es eines mit einer Mittelregelaktion, was nicht ist, was ich will.

Andere Tipps

Die Syntaxfehler von Ihrem zweiten Anruf kommt nach yyparse. Wenn Sie die Umleitung haben, macht Sie Grammatik ein YYACCEPT, die der Parser sofort zurückkehren verursacht, ohne mehr etwas zu lesen. Auf dem zweiten Aufruf gelesen das erste Token ist ein NEWLINE, die Fälle der Fehler (die Grammatik nicht für Leerzeilen erlaubt.)

Ohne Umleitung gibt es keine YYACCEPT, so dass die Grammatik läuft weiter, die Newline Lesen und Rückkehr auf das Ende der Eingabe erreicht.

  1. Sie wirklich wirklich sollte mit LALR Linksrekursion verwenden (1) Parser-Generatoren. Rechts Rekursion erfordert, dass alle Elemente auf den Parser-Zustand Stapel verschoben werden, bevor auch nur eine einzige Reduktion erfolgen kann. Sie können sich vorstellen, was das bedeutet Erholung für Fehler.

  2. Was genau ist external_cmd? Es sieht ein bisschen wie es früh reduziert wird, aber es ist schwer zu sagen, weil Sie es nicht sind.

  3. Warum ist YYACCEPT nach einer Umleitung aufgerufen? Wenn Sie beabsichtigen, den Parser in jeder Zeile neu zu starten, dann sollten Sie nicht die rekursive Eingang Sammler haben. Solange Sie es tun haben, keine YYACCEPT tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top