# IF Anweisung in Flex bison realisieren



## matrix1 (15. April 2010)

Hallo,
kann jemand mir dabei helfen eine If Schleife in Flex zu realisieren.
Das hier ist ein beispiel. Als erstes will ich es schaffen einen jump befehl hinzubekommen, dass flex JMP als token aufnimmt und dann  in bison so generiert wird, dass bei einem JMP er zu label L1 springt und schleife von vorne beginnt.
Bin sehr dankbar für euere Hilfe.

:L1
IF FLAG AND X"0001"
        EVT 23;
ELSE
        WAIT 500 ms;
        JMP L1;
END IF;


MfG
Matrix


----------



## matrix1 (19. April 2010)

*Implementierung von IF in flex/bison*

Hallo,
ich versuche Gerade IF Anweisung mit Flex/Bison zu realisieren, hab so die Syntax aufgebaut, nun versuche ich die Semantik du deklarieren, leider komme ich nicht voran, bin ganz neu dabei hab nicht viel ahnung, hab schon etliche manuals gelesen, aber non Erfahrung.
dieser Programmablauf ungefähr will ich realisieren:

:L1
IF FLAG AND X"0001"
EVT 23;
ELSE
WAIT 500 ms;
JMP L1;
END IF;

hab nun die Bison datei erstellt:
%token ID IF ELSE OR AND END NAME

%start label
%%

statements: /* allow empty statements */ | stm | statements ';' stm;

stm: ifStatement
   | NAME 
   | NAME expList
   | label;

expList: expression | expList expression;

label: ':' NAME { /*code um label abzuspeichern */ };

ifStatement: IF expression statements
           | IF expression statements ELSE statements;

expression: ID                          { /* code um mit gefundener ID umzugehen */ }
          | expression AND expression   { /* Code um zwei Ausdrücke mit and zu erknüpen */ }
          | expression OR expression
          | '(' expression ')';


und die Flex datei:

%{
#include "ifstatement.h"
%}
%option noyywrap

%%
IF   return IF;
ELSE return ELSE;
OR   return OR;
AND  return AND;
[A-Z]+  { yylval=atoi(yytext); return ID; }
%% 

int main(){



}

Wäre super wenn mir jemand mit der Semantik weiterhelfen könnte.Danke.

MfG

Matrix


----------



## Cromon (19. April 2010)

Ich hab nicht wirklich Ahnung von Flex und Bison, ich habe mir einfach mal kurz eine Seite mit Beispielen angesehen, aber so wie ich das verstanden habe ist ja Flex grundsätzlich lediglich dazu da Eingaben des Benutzers nach Regex-Regeln zu verarbeiten? Was genau meinst du da mit "Implementierung von IF"? Gewöhn dir ausserdem an Code immer in entsprechende Code-Tags zu fassen.


----------



## matrix1 (19. April 2010)

hallo
ich möchte einen interpreter schreiben, der eine if anweisung analysieren soll und die befehle ausführen soll, damit ich nicht alles einzeln eintippen muss.danke

mfg
matrix


----------



## matrix1 (26. April 2010)

*JMP-Befehl in Flex/Bison realisieren*

Hallo allerseits,
hat jemand ne idee wie man den JMP (Jump) Befehlr wie den in Assembler gibt, um zu bestimmten labels zu springen, realisieren kann, bin schon die ganze Zeit dabei, komme einfach nicht drauf, hab herausgefunden dass es eine Funktion namens goto gibt, mit der man zu vordefinierten labels springen kann. Kann mir jemand helfen.Danke.
so ungefähr sieht mein Beispiel aus:

:L1
IF FLAG AND X"0001"
EVT 23;
ELSE
WAIT 500 ms;
JMP L1;
END IF;


----------



## Matthias Reitinger (27. April 2010)

Hallo,

Flex und Bison sind Tools für die syntaktische Analyse. Für die Semantik deiner Sprache musst du schon eigene Algorithmen und Datenstrukturen verwenden. Du könntest dazu den Quelltext beispielsweise (mit Bison) zuerst in einen abstrakten Syntaxbaum transformieren und diesen dann ablaufen.

Grüße,
Matthias


----------



## matrix1 (27. April 2010)

Hallo,
vielen Ddank für deine Antwort, 
ich habe bereits ein Syntaxbaum erstellt, habe nun auch versucht goto funtion zu implementieren, hatte vergessen dass dies ja eine syntaktische analyse ist und keine Funktionsprogrammierung.  Leider kommt bei mir die ganze Zeit eine Fehlermeldung ich häng dir mal die .l und .y dateien mal an, wäre super wenn du drüber schauen könntest. Hab erst mit goto versucht wenn das klappt will ich es zu JMP umsetzen, da dieser interpreter ja JMP erkennen soll und dsann sagen soll wohin e springt, soweit muss ich kommen.Danke.

MfG
Matrix


----------



## deepthroat (27. April 2010)

Hi.





matrix1 hat gesagt.:


> Hallo,
> vielen Ddank für deine Antwort,
> ich habe bereits ein Syntaxbaum erstellt, habe nun auch versucht goto funtion zu implementieren, hatte vergessen dass dies ja eine syntaktische analyse ist und keine Funktionsprogrammierung.  Leider kommt bei mir die ganze Zeit eine Fehlermeldung


Welche?


matrix1 hat gesagt.:


> ich häng dir mal die .l und .y dateien mal an, wäre super wenn du drüber schauen könntest.


Ich hab's mir mal angeschaut. Komisch ist, dass die definierte Grammtik irgendwie nicht richtig zu deinem Beispielcode passt. Bist du sicher das du die Dateien nicht 1:1 von hier übernommen hast?! :suspekt:

Wie Matthias schon sagte, wenn du erstmal den Syntaxbaum hast, dann kannst du ihn auch traversieren. Du mußt dann nur programmieren was passieren soll wenn du auf einen JMP Knoten im Baum triffst. D.h. du müßtest dann das entsprechende LABEL suchen (oder gleich in einer Tabelle abspeichern) und dann an diese Stelle (bzw. die darauffolgende Anweisung) springen.

Gruß


----------



## matrix1 (27. April 2010)

Hallo,
Danke für deine schnelle Antwort.
Mir sind einige Sachen unklar, was meinst du mit traversieren und welche tabelle meinst du, habe ich das mit 

label_stmt: Name ':' {printf("%s:\n",$1);}

goto_stmt: GOTO NAME ';' {printf("\tJNZ %s\n",$2);}

nicht initialisiert.

Kannst du mir anhand eines Beispiels zeigen, was genau du meinst.Danke.


----------



## deepthroat (27. April 2010)

matrix1 hat gesagt.:


> Mir sind einige Sachen unklar, was meinst du mit traversieren


Ich meine du kannst den Baum dann durchlaufen wie du möchtest.


matrix1 hat gesagt.:


> und welche tabelle meinst du,


Entweder du suchst in dem Baum nach dem entsprechenden Ziel-Label von dem JMP Befehl oder du legst dir gleich eine Tabelle an, wo du einem Label gleich einen Knoten im Baum zuordnen kannst.


matrix1 hat gesagt.:


> habe ich das mit
> 
> label_stmt: Name ':' {printf("%s:\n",$1);}
> 
> ...


Was meist du mit initialisiert? Du gibst da nur etwas auf der Standardausgabe aus. Du mußt es in den Syntaxbaum mit aufnehmen (und optional auch noch einen Eintrag in die Label-Tabelle machen).

Gruß


----------



## matrix1 (27. April 2010)

hallo,
kannst du mir anhand eines Beispiels zeigen wie man eine tabelle anlegt, soweit bin ich noch nicht, hab gerade erst angefangen flex bison richtig anzuwenden kenne mich noch nicht so genau aus.Danke.

Gruß


----------



## deepthroat (27. April 2010)

matrix1 hat gesagt.:


> hallo,
> kannst du mir anhand eines Beispiels zeigen wie man eine tabelle anlegt, soweit bin ich noch nicht, hab gerade erst angefangen flex bison richtig anzuwenden kenne mich noch nicht so genau aus.Danke.


Ganz simpel könntest du erstmal ein Array dafür nehmen.

```
typedef struct { const char name[20];
LabelStmt* link;
} label_stmt;

label_stmt label_tab[100];
```
Gruß


----------



## matrix1 (28. April 2010)

Hallo,
ich hab hier was gefunden, kann dies mir abhilfe schaffen. genauso kann ich doch auch für meinen JMP Befehl machen oder.
Kannst dir mal anschauen.Danke.

http://www.mikrocontroller.net/topic/126816

MfG
Matrix


----------



## deepthroat (28. April 2010)

Hi.





matrix1 hat gesagt.:


> Hallo,
> ich hab hier was gefunden, kann dies mir abhilfe schaffen. genauso kann ich doch auch für meinen JMP Befehl machen oder.
> Kannst dir mal anschauen.Danke.
> 
> http://www.mikrocontroller.net/topic/126816


Was genau meinst du? Du erwartest doch wohl nicht das ich mir das alles durchlese, oder?!

Gruß


----------



## matrix1 (28. April 2010)

Hallo,
ne da ist ein beispiel wie ich die Tabelle mit Kommandos fülle oder wie ne neue Eingabe zeile dann verglichen wird.
dann ne kleine Zusammenfassung:

*eine Tabelle, in der alle Kommandowörter aufgeführt sind und die dazu zugehörigen Funktionen, die aufzurufen
sind:*

```
struct Command
{
  const char*  Keyword;
  FktPtr       Function;
};
```
*Interpreter kann max. 20 Kommandos halten :
*

```
#define MAX_COMMANDS 20
struct Command Commands[ MAX_COMMANDS ];
int NrCommands = 0;
```
*Jetzt noch eine Funktion, die ein neuese Kommando einfügt:*

```
unsigned char AddCommand( const char* Keyword, FktPtr Function )
{
  if( NrCommands >= MAX_COMMANDS )
    return FALSE;

  Commands[NrCommands].Keyword = Keyword;
  Commands[NrCommands].Function = Function;
  NrCommands++;

  return TRUE;
}
```
*Beispiel:*

```
void TestFkt( int count, int* args )
{
}

void EchoFkt( int count, int* args )
{
  int i;

  for( i = 0; i < count; ++i )
    printf( "%d\n", args[i] );
}

int main()
{
  AddCommand( "test", TestFkt );
  AddCommand( "echo", EchoFkt );
}
```
*vom Benutzer kommt eine Eingabezeile. Was ist zu tun?
Das erste Wort aus der Einagbezeile ist zu extrahieren. Damit wird in die Kommandotabelle gegangen und der entsprechende Eintrag gesucht. Wird einer gefunden, wird die zugehörie Funktion aufgerufen*

```
void Execute( const char* Input )
{
  size_t i, j;
  char Command[20];

  // Whitespace am Anfang überlesen

  while( Input[i] != '\0' && ( Input[i] == ' ' || Input[i] == '\t' ||
                               Input[i] == '\n' ) )
    i++;
  if( Input[i] == '\0' )
    return

  j = 0;
  while( Input[i] != '\0' && !( Input[i] == ' ' || Input[i] == '\t' ||
                                Input[i] == '\n' ) ) {
    Command[j++] = Input[i++];

  for( i = 0; i < NrCommands; ++i ) {
    if( stricmp( Commands[i].Keyword, Command ) == 0 ) {
      (*Commands[i].Function)();
      return;
    }
  }

  printf( "Don't know how to \'%s\'\n", Command );
}
```
so ungefähr wäre das passabel zu meinem beispiel.Danke.

MfG
matrix


----------



## deepthroat (28. April 2010)

Hi.





matrix1 hat gesagt.:


> so ungefähr wäre das passabel zu meinem beispiel.Danke.


Wenn du damit meinst das dort auch eine Tabelle mit Zuordnungen von Namen und (in diesem Fall) Funktionen verwendet wird, dann ja.

Bitte verwende die Code-Tags für deine Codeschnipsel. Danke.

Gruß


----------



## matrix1 (4. Mai 2010)

Hallo,
lange nicht mehr voneinander gehört,
Hab das Programm soweit erweitert, hab auch den label und jump befehl implementiert, damit er im Baum danach suchen kann, aber irgendwie klappt das nicht, ich glaube da stimmt was nicht mit der implementierung von label_stmt und jmp_stmt, 

label_stmt: ':' NAME 
    { $$ = newStmtNode(LabelK);
      $$->child[0] = $2;

    }

jmp_stmt: JMP NAME
  {$$ = newStmtNode(JmpK);
  $$->attr.name = strdup($2);  

de Pointer auf den String in attr.name glaube ich ist nicht in ordnung.
Kannst du mir irgendwie weiterhelfen, Ich habe die files in bitbucket hochgeladen kannst dir runterladen in 
http://bitbucket.org/matrix/changed-tiny.

Gruß
Matrix


----------



## deepthroat (4. Mai 2010)

Hi.

Bitte verwende die Code-Tags! 

Ein Label ist ein Nichtterminalsymbol und besteht aus einem Doppelpunkt und einem Bezeichner. Ein zusätzliches Token NAME ist somit überflüssig.

Gruß


----------



## matrix1 (4. Mai 2010)

Hallo, 
hab ne weitere Idee, weiß aber nicht wie ich das implementieren soll.
Ich mach einen Knoten für den label, aber wie schaffe ich denn den namen des Labels in diesem Knoten zu speichern
und wie mache ich die Ausgabe.

Ich glaube so ist es nicht in Ordnung:
label_stmt: ':' NAME
{ $$ = newStmtNode(LabelK);
$$->child[0] = $2;

}

Gruß
 matrix



deepthroat hat gesagt.:


> Hi.
> 
> Bitte verwende die Code-Tags!
> 
> ...



meinst du etwa so


```
label_stmt: ':' ID 
    { $$ = newStmtNode(LabelK);
      /*$$->child[0] = $2;*/
	$$->attr.name = strdup($2);

    }

jmp_stmt: JMP ID
	{$$ = newStmtNode(JmpK);
	/*$$->attr.name = strdup($2);*/
	$$->child[0] = $2;	

	}
```
danke.


----------



## deepthroat (4. Mai 2010)

Hi.

Ich meine zuallererst mal deine Tokendefinition:

```
"label" {return NAME;}
```
Wozu soll das denn gut sein? Wenn dort das Schlüsselwort "label" auftaucht, lieferst du NAME zurück. Laut deines Beispiels gibt es überhaupt kein "label" Schlüsselwort.

Außerdem hast du hier dem Token NAME überhaupt keinen Wert zugewiesen. Wie willst du dann später noch auf den Namen zugreifen?

Gruß


----------



## matrix1 (4. Mai 2010)

hallo,
weiß selber net warum ich das gemacht habe, stimmt ja ich gebe ja keine eingabe von label ein brauche ich ja auch nicht, aussschließlich will ich ja, das wenn JMP L1 eingegeben wird, dann ausgegeben wir dass keyword JMP wurde benutzt zum Label L1, aber dann ist es doch in Ordnung wenn ich schreibe


```
jmp_stmt: JMP ID
	{$$ = newStmtNode(JmpK);
	/*$$->attr.name = strdup($2);*/
	$$->child[0] = $2;	

	}
```

also folglich müsste doch L1 im Baumknoten abgespeichert werden und bei der Ausgabe mit


```
case JmpK:
          printf("JMP\n","to Label: %s\n",tree->attr.name);
          break;
```

ausgegeben werden

hallo,
jetzt fällt mir wieder ein warum ich label genutzt hatte, da mein Code ja mit :L1 beginnt, dann muss ich doch eigentlich statt label 
den" :" als mein Token bezeichnen und als mein label deklarieren oder.

Gruß
Matrix


----------



## deepthroat (4. Mai 2010)

Hi.





matrix1 hat gesagt.:


> weiß selber net warum ich das gemacht habe, stimmt ja ich gebe ja keine eingabe von label ein brauche ich ja auch nicht, aussschließlich will ich ja, das wenn JMP L1 eingegeben wird, dann ausgegeben wir dass keyword JMP wurde benutzt zum Label L1, aber dann ist es doch in Ordnung wenn ich schreibe
> 
> 
> ```
> ...


Wie ist die Eingabe und was wird jetzt ausgegeben?


			
				matrix1 hat gesagt.:
			
		

> jetzt fällt mir wieder ein warum ich label genutzt hatte, da mein Code ja mit :L1 beginnt, dann muss ich doch eigentlich statt label
> den" :" als mein Token bezeichnen und als mein label deklarieren oder.


Im Grunde gibt es 2 Möglichkeiten. Man könnte die Label schon in der lexikalischen Analyse verarbeiten und ein Token LABEL mit dem entsprechenden Bezeichner als Wert zurückgeben:

```
:[a-zA-Z][a-zA-Z0-9_]*  { yylval.name = strdup(yytext + 1); return LABEL; }
```
Oder (wie zuerst vorgeschlagen), man liefert einfach den Doppelpunkt als TOKEN zurück und behandelt ein Label als ein Nichtterminal in der Grammatik als eine Folge von ':' ID.

Gruß


----------



## matrix1 (4. Mai 2010)

hallo,
ok hab die zweite Variante gewählt

lex:

```
":" {return yytext[0];}
```

soll ich dann wenn ich als token deklariere einfach ein : hinschreiben, nimmt er das an

```
%token :
```


```
label_stmt: ':' ID
```

hallo,

die erste Variante würde ja so aussehen:


```
:[a-zA-Z][a-zA-Z0-9_]*  { yylval.name = strdup(yytext + 1); return LABEL; }
```


```
%token IF THEN ELSE END REPEAT UNTIL SCAN PRINT ID NUM EQUAL FOR WHILE RETURN JMP LABEL
```


```
%type <tree> read_stmt write_stmt exp simple_exp term factor jmp_stmt label_stmt
```


```
label_stmt: ID LABEL
    { $$ = newStmtNode(LabelK);
      /*$$->child[0] = $2;*/
	$$->attr.name = strdup($2);

    }
```


----------



## deepthroat (4. Mai 2010)

matrix1 hat gesagt.:


> hallo,
> ok hab die zweite Variante gewählt
> 
> lex:
> ...


Nein, das TOKEN steht für sich selbst. Das brauchst du dann gar nicht.

Gruß


----------



## deepthroat (4. Mai 2010)

matrix1 hat gesagt.:
			
		

> hallo,
> 
> die erste Variante würde ja so aussehen:
> 
> ...


Nein. Wieso "ID LABEL?
	
	
	



```
label_stmt: LABEL 
 { $$ = newStmtNode(LabelK);
   $$.attr.name = $1.name;
  }
```
Gruß


----------



## matrix1 (4. Mai 2010)

Hallo,
Danke für deine Hilfe.
Nun habe ich mein Label definiert, dann sieht also mein JMP dann so aus:


```
label_stmt: ':' ID
    { $$ = newStmtNode(LabelK);
      $$.attr.name = $2.name;
    }
```


```
jmp_stmt: JMP ID
	{$$ = newStmtNode(JmpK);
	/*$$->attr.name = strdup($2);*/
	$$.attr.name = $2.name;	

	}
```

Gruß
Matrix


----------



## deepthroat (4. Mai 2010)

Du mußt das Ganze doch wirklich nur analog der bereits vorhandenen Regeln machen.
	
	
	



```
label_stmt: ':' ID
    { $$ = newStmtNode(LabelK);
      $$.attr.name = $2;
    }
```


```
jmp_stmt: JMP ID
	{$$ = newStmtNode(JmpK);
	$$.attr.name = $2;
	}
```
Gruß


----------



## matrix1 (4. Mai 2010)

deepthroat hat gesagt.:


> Du mußt das Ganze doch wirklich nur analog der bereits vorhandenen Regeln machen.
> 
> 
> 
> ...



hallo,
Vielen dank nochmal.

aber leider kommen mehrere warnungen:
1 nonterminal useless in grammar: label_stmt
1 rule useless in grammar: label_stmt: ':' ID

was hat das zu bedeuten.danke.

Gruß
Matrix


----------



## deepthroat (4. Mai 2010)

matrix1 hat gesagt.:


> hallo,
> Vielen dank nochmal.
> 
> aber leider kommen mehrere warnungen:
> ...


Das heißt nur das eine Regel wie A -> a b eigentlich nutzlos ist, da diese Regel keine Alternativen und keine anderen Nichtterminale enthält. Überall da wo das Nichtterminal (in diesem Fall label_stmt) auftaucht könnte dies auch direkt durch die rechte Seite ersetzen.

Bison entfernt die "nutzlose" Regel um einen kompakteren Parser zu generieren.

Gruß


----------



## jkallup (4. Mai 2010)

Hallo,

ich habe hier zum Beispiel einen Compiler mit yacc von Albert Gräf
realisiert, hierzu ein kleiner Ausschnitt:

leider in Pascal, aber vielleicht hilft es ja weiter 

Gruß
Jens


```
${

type
  lbl = record
    else_label: Integer;
    end_label : Integer;
  end;

%}

%type <lbl>

%token TOK_IF TOK_ELSEIF TOK_ELSE



ifExpression
        : expr {
          if fld_counter-2 <= 1 then
          begin
            data_code.Add(#9 + 'fld qword [@null_value]');
            data_code.Add(#9 + 'faddp');
            fld_counter := 0;
          end;

        } ifRelation expr {

          if fld_counter-2 <= 1 then
          begin
            data_code.Add(#9 + 'Fld qword [@null_value]');
            data_code.Add(#9 + 'Faddp');
            fld_counter := 0;
          end;

          handle_expr := true;
          push_values := true;
        }
        ;

ifRelation
        : '='      { if_reltype := 0; }
        | '#'      { if_reltype := 1; }
        | '<'      { if_reltype := 2; }
        | '>'      { if_reltype := 3; }
        | '<' '='  { if_reltype := 4; }
        | '>' '='  { if_reltype := 5; }
        | '<' '>'  { if_reltype := 6; }
        | '=' '<'  { if_reltype := 4; }
        | '=' '>'  { if_reltype := 5; }
        ;

ifStatement
        : TOK_IF {
          push_values := true;
          print_string := true;

          if_counter := if_counter + 1;
        } ifExpression {

          push_values := false;

          $<lbl>$.else_label := new_label+1;
          $<lbl>$.end_label  := new_label;

          if (ist_schon_eval = false) and (in_object_code = false) then
          begin
            data_code.Add(#9 + 'fxch st1');
            data_code.Add(#9 + 'fucompp');
            data_code.Add(#9 + 'fstsw ax');
            data_code.Add(#9 + 'sahf');

            case if_reltype of
              0: begin data_code.Add(#9 + 'jne  near Le' + IntToStr($<lbl>$.else_label)); end;
              1: begin data_code.Add(#9 + 'je   near Le' + IntToStr($<lbl>$.else_label)); end;
              2: begin data_code.Add(#9 + 'jnl  near Le' + IntToStr($<lbl>$.else_label)); end;
              3: begin data_code.Add(#9 + 'jng  near Le' + IntToStr($<lbl>$.else_label)); end;
              4: begin data_code.Add(#9 + 'jnle near Le' + IntToStr($<lbl>$.else_label)); end;
              5: begin data_code.Add(#9 + 'jnge near Le' + IntToStr($<lbl>$.else_label)); end;
              6: begin data_code.Add(#9 + 'je   near Le' + IntToStr($<lbl>$.else_label)); end;
            end;
          end;

          new_label := new_label + 1;
          $<lbl>$.else_label := new_label;

        } StatementSequence {

          //new_label := new_label + 1;
          $<lbl>3.end_label := new_label;

          if (ist_schon_eval = false) and (in_object_code = false) then
          begin
            data_code.Add(#9 + 'jmp near Lj' + IntToStr($<lbl>3.end_label-1));
            data_code.Add('Le'               + IntToStr($<lbl>3.end_label) + ':');
          end else
          if (ist_schon_eval = true) then
          begin
            if if_counter > 1 then
            begin
//              FObjectCode.Add('jmp near Le'+inttostr($<lbl>3.end_label));
//              FObjectCode.Add('::Lj'+inttostr($<lbl>3.end_label+1)+':');
            end;
          end;

          new_label := new_label + 1;
          $<lbl>3.end_label := new_label;

        } elseif_stat TOK_ENDIF {

          if if_counter-1 < 0 then
          raise Exception.Create('ENDIF hier nicht erwartet - IF muss vorrangehen.'+#10+
          inttostr(line_no));

          dec(if_counter);

          if (ist_schon_eval = false) and (in_object_code = false) then
          begin
            data_code.Add(#9   + 'jmp near Lj' + IntToStr($<lbl>4.else_label-1));
            data_code.Add('Lj' +                 IntToStr($<lbl>4.else_label-1) + ':');
          end else
          if ist_schon_eval = true then
          begin
            if (if_counter >= 1) then
            begin
              //showmessage(inttostr(if_counter+$<lbl>4.else_label)+' : '+inttostr($<lbl>4.else_label));
              if ((if_counter+$<lbl>4.else_label) - (($<lbl>4.else_label)-(if_counter+$<lbl>4.else_label))) = 1 then
              FObjectCode.Add(#9 + 'jmp near   Lj' + IntToStr($<lbl>4.else_label)) else
              FObjectCode.Add(#9 + 'jmp near   Lj' + IntToStr($<lbl>4.else_label+4));
            end else
            begin
              FObjectCode.Add(#9   + 'jmp near  Le' + IntToStr($<lbl>4.else_label-1));
              FObjectCode.Add('Lj' +                 IntToStr($<lbl>4.else_label+1) + ':');

              if if_counter < 1 then
              FObjectCode.Add('Le'+IntToStr($<lbl>3.end_label-2) + ':');
            end;
          end;

//          ist_schon_eval := false;
        }
        ;
elseif_stat
        :
        | StatementSequence             {
          $<lbl>$.end_label := new_label;
        }
        | TOK_ELSEIF ifExpression {
          if_counter := if_counter + 1;

          $<lbl>$.else_label := new_label;
          $<lbl>$.end_label  := new_label;

          new_label := new_label + 1;   } StatementSequence {
          new_label := new_label + 1;

          $<lbl>$.end_label := new_label;

          data_code.Add(#9+'jMP near Lj' + IntToStr($<lbl>3.end_label));
          data_code.Add('Le'             + IntToStr($<lbl>3.end_label) + ':');

        } elseif_stat {
          new_label := new_label + 2;
          $<lbl>$.else_label := $<lbl>3.else_label;

          data_code.Add(#9+'jmp near Lj' + IntToStr($<lbl>3.else_label));
          data_code.Add('Lj'             + IntToStr($<lbl>3.else_label) + ':');
        }
        | TOK_ELSE  StatementSequence  { $<lbl>$.end_label := new_label; }
        ;
```


----------



## matrix1 (5. Mai 2010)

Guten Morgen,

meine Ausgabe in der switch anweisung sollte doch dann wie folgt aussehen:



deepthroat hat gesagt.:


> Du mußt das Ganze doch wirklich nur analog der bereits vorhandenen Regeln machen.
> 
> 
> 
> ...



aber leider erscheint eine Fehlermeldung:

error: request for member 'attr' in something not a structure or union

was heißt as.
Danke
Gruß
Matrix


----------



## deepthroat (5. Mai 2010)

Hi.





matrix1 hat gesagt.:


> aber leider erscheint eine Fehlermeldung:
> 
> error: request for member 'attr' in something not a structure or union
> 
> was heißt as.


Das heißt das ich das nur so schnell dahingeschrieben habe und dabei nicht drauf geachtet habe von welchem Typ $$ ist. $$ ist ein Zeiger:

```
$$->attr.name = $2;
```
Gruß


----------



## matrix1 (5. Mai 2010)

Hallo,
habs eben gerade auch herausgefunden, dass es so sein muss wie du gesagt hast.Danke nochmal.

Gruß

Hallo,
aber leider macht der compiler nicht das was er machen soll,
er erkennt kein :, wenn ich die Zeile mit : beginne da mein label am Anfang steht, woran kann denn das liegen fehlt mir nochwas bei der Implementierung, oder habe ich etwas übersehen.Danke.

Gruß


----------



## deepthroat (5. Mai 2010)

matrix1 hat gesagt.:
			
		

> Hallo,
> aber leider macht der compiler nicht das was er machen soll,
> er erkennt kein :, wenn ich die Zeile mit : beginne da mein label am Anfang steht, woran kann denn das liegen fehlt mir nochwas bei der Implementierung, oder habe ich etwas übersehen.Danke.


Zeig deinen Code (hier oder bring den Code in bitbucket auf den neuesten Stand).

Gruß


----------



## matrix1 (5. Mai 2010)

Hallo,



deepthroat hat gesagt.:


> Zeig deinen Code (hier oder bring den Code in bitbucket auf den neuesten Stand).
> 
> Gruß



habs in http://bitbucket.org/matrix/changed-tiny aktualisiert.Danke.

Gruß

hallo,
hab meinen Fehler gefunden, hatte bei 

stmt: if....
|....
|...
...
|  label_stmt 

leider auskommentiert habe gerade erst gemerkt.
Geht trotzdem nicht, wäre super wenn du reinschauen könntest.Danke.

Gruß


----------



## deepthroat (5. Mai 2010)

Hi.

Bei dir dürfen Bezeichner nur aus Buchstaben bestehen. Üblicherweise definiert man Bezeichner als Token die mit einem Buchstaben anfangen und dann aus einer Folge von Buchstaben oder Ziffern bestehen. Evlt. auch mit Unterstrich.

Außerdem muß ein Label laut deiner Grammatik mit einem Semikolon abgeschlossen werden.

Gruß


----------



## matrix1 (5. Mai 2010)

Hallo,

na gut das Problem habe ich auch gelöst mit


```
[a-zA-Z][a-zA-Z0-9_]* {yylval.name = strdup(yytext); return  ID;}
```

aber der JMP geht immer noch nicht,  gibt mir Fehler zurück, stimmt da was nicht, sollte doch eigentlich gehen.

Danke vielmals für deine Hilfe und deine Geduld.

MfG
Matrix


----------



## deepthroat (5. Mai 2010)

matrix1 hat gesagt.:


> Hallo,
> 
> na gut das Problem habe ich auch gelöst mit
> 
> ...


Wie sieht die Eingabe aus, was ist die Ausgabe bzw. welcher Fehler wird zurückgegeben?

Du läßt dir aber auch alles aus der Nase ziehen...

Gruß


----------



## matrix1 (5. Mai 2010)

Hallo,

Ja gut wenn ich zum beispiel das hier eingebe:


```
:L1;
if(x>0)
y=0;
else
JMP L1;
end;
```

gibt er mir aus (ohne den JMP L1):


```
Label: L1
If
    Op: >
        Id: x
        const: 0

    Assign to: y
         const: 0
```

sieht auch gut aus aber mit JMP L1 macht er nichts sagt (in der Eingabeaufforderung) syntax error, weil es ja auch so definiert ist, sollte mir aber zurückgeben:


```
JMP
        to Label: L1
```

wie ich es für die Ausgabe definiert habe.

das hier habe ch bei der Ausgabe definiert:


```
case JmpK:
          printf("JMP\n","to Label: %s\n",tree->attr.name);
```

Danke.

Hallo,

eine kleine Frage, ich habe doch in der lex file die ganzen Eingaben definiert, das heißt ich habe sie alle klein geschrieben, bedeutet die Eingabe muss auch klein sein, definiere ich alle groß muss die Eingabe auch Groß sein?

und ja gut wenn ich JMP klein schreibe dann macht er etwas, gibt dann JMP aus, aber nicht to label: L1, 
ich glaube  hier muss ich was anderes definieren, sollte statt dem komma zwischen JMP und to label was anderes sein

```
case JmpK:
          printf("JMP\n","to Label: %s\n",tree->attr.name);
```

Danke.
Gruß


----------



## deepthroat (5. Mai 2010)

matrix1 hat gesagt.:


> sieht auch gut aus aber mit JMP L1 macht er nichts sagt (in der Eingabeaufforderung) syntax error, weil es ja auch so definiert ist, sollte mir aber zurückgeben:


Kannst du mal bitte ordentlich schreiben und Satzzeichen verwenden. Ich habe keine Lust noch lange herausfinden zu müssen was das bedeuten soll. Ich schreibe doch auch nicht in Kauderwelsch, oder?!


matrix1 hat gesagt.:


> ```
> case JmpK:
> printf("JMP\n","to Label: %s\n",tree->attr.name);
> ```


Das solltest du nochmal scharf ankucken. Die Ausgabe ist *immer* nur "JMP\n".

Außerdem, ist dein Lexer denn Groß-/Kleinschreibung tolerant? ;-]

Gruß


----------



## matrix1 (5. Mai 2010)

Hallo,

Habs endlich hinbekommen, er gibt genau das aus was er ausgeben soll, du meine Güte das war aber ein harter brocken, zum Glück es klappt alles.

Deepthroat ich muss sagen du hasst mir sehr viel geholfen, ich weiß ich bin dir bestimmt sehr auf die Nerven gegangen, aber DANKE dass du soviel Geduld für mich gezeigt hast. Danke nochmal für all deine Hilfe. Falls ich weitere Hilfe brauchen sollte melde ich mich bei dir. Danke für alles.

Einen schönen tag noch.

Mit freundlichen grüßen
Matrix


----------



## matrix1 (7. Mai 2010)

Hallo,
da bin ich wieder, hab mal ne Frage, ich habe jetzt ikm nachhinein noch weitere Sachen hinzugefügt, die ganzen operatoren wie >=, <=, !=, und logische OPeratoren and und or, klappt alles wunderbar, nun wollte ich, "++" {return INC} also den Increment Operator deklarieren, leider klappt er bei mir nicht, also der compiler erkennt schon "++" und gibt INC aus, aber ich will, dass er auch den bezeichner ausgibt, der Inkrementiert werden soll (++x), sollte doch fast das selbe sein wie mein JMP Befehl oder? 
Ich habe die neuen Files wieder in http://bitbucket.org/matrix/changed-tiny angehängt, wäre super, wenn du mal nachschauen könntest.Danke.

Gruß
Matrix


----------



## deepthroat (7. Mai 2010)

Hi.





matrix1 hat gesagt.:


> da bin ich wieder, hab mal ne Frage, ich habe jetzt ikm nachhinein noch weitere Sachen hinzugefügt, die ganzen operatoren wie >=, <=, !=, und logische OPeratoren and und or, klappt alles wunderbar, nun wollte ich, "++" {return INC} also den Increment Operator deklarieren, leider klappt er bei mir nicht, also der compiler erkennt schon "++" und gibt INC aus, aber ich will, dass er auch den bezeichner ausgibt, der Inkrementiert werden soll (++x), sollte doch fast das selbe sein wie mein JMP Befehl oder?




```
"++"[a-zA-Z] {return INC;}
```
Warum willst du denn einen Operator mit einem Buchstaben als Token ansehen? Was ist wenn dazwischen Leerzeichen stehen? Was ist mit einem Postinkrement-Operator?

Und warum machst du es dann nicht so wie bei den anderen Token die einen Wert haben?


matrix1 hat gesagt.:


> Ich habe die neuen Files wieder in http://bitbucket.org/matrix/changed-tiny angehängt, wäre super, wenn du mal nachschauen könntest.


Installier dir doch bitte mal Mercurial. Es ist etwas mühsehlig die Dateien immer da runterzuladen und die Änderungen zu den letzten Versionen rauszusuchen. Außerdem ist BitBucket dafür nun auch wieder nicht gedacht einfach nur profan Dateien hochzuladen. Siehe http://bitbucket.org/help/GettingStartedWithMercurial#mercurial-primer

Gruß


----------



## matrix1 (7. Mai 2010)

deepthroat hat gesagt.:


> Hi.
> 
> ```
> "++"[a-zA-Z] {return INC;}
> ...



weil die Eingabe so aussieht: ++x, wenn ich nur die ++ Eingabe mache dann erkennt er es ja, ich will aber,da dass er ausgibt


```
INC
     Id: x
```

z.b.

danke.



deepthroat hat gesagt.:


> Hi.
> 
> ```
> "++"[a-zA-Z] {return INC;}
> ...



was meinst du damit, klappt es nicht, wenn ich wie bei meinem JMP befehl nur "++ " und dann so ne art label_stmt definiere also ic meine so:


```
id_stmt: '++' ID
	{ $$ = newStmtNode(BeK);
       $$->attr.name = $2;
  	}

inc_stmt: INC ID
	{
	$$ = newStmtNode(IncK);
	$$->attr.name = $2;
	}
```

kann es nicht so klappen.Danke.

Gruß



> Was ist mit einem Postinkrement-Operator?



Ich benutze einen Pre-inkrement operator deshalb.

Danke.
Gruß


----------



## matrix1 (10. Mai 2010)

Guten Morgen deepthroat,

Ich hab also meiner Aufgabenstellung nach alles hinbekommen, nun habe ich eine neue Problematik, darauf komme ich leider nicht kannst mir ja helfen, das wäre super.

Bei einer normalen If-Anwisung, gibt mr meine Ausagbe alles aus was es tun soll, nur  jetzt ist es einbißchen anders. Erst wenn ich einen JMP befehl eingegeben hatte hatte er es erkannt und hat zugleich den Label angegeben. Nun aber wenn z.B ich eine If anweisung angebe, und die Anweisung des If's zutrifft, tut er ja den Befehl aus, ansonsten (else) soll er eine andere Anweisung ausführen, aber bei der Ausgabe soll angegeben werden, if wurde benutzt, welcher operator Konstante Bezeichner, tut ja mein compiler auch, nun soll er die erste Anweisung ausgeben (vor dem else) und dann soll er direkt ausgeben, JMP zum ende der If Schleife, da die Anweisung erfüllt wurde und die Anweisung nach der else nicht nötig ist, dann erst soll er die zweite Anweisung ausgeben. Ich verdeutliche dies mal anhand eines Beispiels mit zugewiesenen Adressen:

Eingabe      Adr  Ausgabe


```
if(x==0)        10   if(x==0)
Wait 5          20   WAIT 5
else            30   JMP 50
Wait 1          40   WAIT 1
end             50   END
```

so ungefähr hoffe du verstehst was ich meine.

Danke Nochmals.

MfG
Matrix

Hallo,

hab mir überlegt, dass ich eine spezielle if-Anweisung benötige, z.B.

```
IF exp jmp_stmt_end stmt_seq END
```
dass heißt, der compiler müsste erkennen dass in der if Anweisung ein end eingeben wurde und dass genauso wie bei label abspeichert und dann bei der Ausgabe den JMP End ausgibt, wie ich ihn oben definiert habe, was hälst du davon.

Danke.

MfG
Matrix


----------



## deepthroat (10. Mai 2010)

Hi.





matrix1 hat gesagt.:


> Bei einer normalen If-Anwisung, gibt mr meine Ausagbe alles aus was es tun soll, nur  jetzt ist es einbißchen anders. Erst wenn ich einen JMP befehl eingegeben hatte hatte er es erkannt und hat zugleich den Label angegeben. Nun aber wenn z.B ich eine If anweisung angebe, und die Anweisung des If's zutrifft, tut er ja den Befehl aus, ansonsten (else) soll er eine andere Anweisung ausführen, aber bei der Ausgabe soll angegeben werden, if wurde benutzt, welcher operator Konstante Bezeichner, tut ja mein compiler auch, nun soll er die erste Anweisung ausgeben (vor dem else) und dann soll er direkt ausgeben, JMP zum ende der If Schleife, da die Anweisung erfüllt wurde und die Anweisung nach der else nicht nötig ist, dann erst soll er die zweite Anweisung ausgeben. Ich verdeutliche dies mal anhand eines Beispiels mit zugewiesenen Adressen:
> 
> Eingabe      Adr  Ausgabe
> 
> ...


Du willst jetzt also den Code übersetzen, so dass kein else mehr in dem Code ist, sondern ein JMP auf bzw. hinter das Ende des Else-Anweisungsblocks gemacht wird.



matrix1 hat gesagt.:


> hab mir überlegt, dass ich eine spezielle if-Anweisung benötige, z.B.
> 
> ```
> IF exp jmp_stmt_end stmt_seq END
> ...


Du hast doch aber schon alles abgespeichert. Also brauchst du auch keine spezielle if-Anweisung.

Bei einer if-else Anweisung hast du einen *If* Knoten im AST und dieser hat als 3. Kindknoten den else-Anweisungsblock. Wenn du jetzt Code anhand des AST generierst, dann mußt du doch sowieso erstmal die Zeilennummern generieren und dementsprechend auch einen JMP generieren.

Gruß


----------



## matrix1 (10. Mai 2010)

Hallo,

ja genau wenn die if anweisung x==0 zutrifft dann ist ja Wait 5 in ordnung und bei der Ausgabe soll direkt nach WAIT 5 dann JMP stehen und danach dann Wait 1.  Die Adressen habe ich als Beispiel angehängt, um JMP zu verstehen.


```
Eingabe     Adr.  Ausgabe
if(x==0)        10   if(x==0)
Wait 5          20   WAIT 5
else            30   JMP 50
Wait 1          40   WAIT 1
end             50   END
```



> Wenn du jetzt Code anhand des AST generierst, dann mußt du doch sowieso erstmal die Zeilennummern generieren und dementsprechend auch einen JMP generieren.



Ich versteh das nicht so ganz mit den Zeilennummern generieren.Dannke.

Gruß


----------



## deepthroat (10. Mai 2010)

matrix1 hat gesagt.:


> Hallo,
> 
> ja genau wenn die if anweisung x==0 zutrifft dann ist ja Wait 5 in ordnung und bei der Ausgabe soll direkt nach WAIT 5 dann JMP stehen und danach dann Wait 1.  Die Adressen habe ich als Beispiel angehängt, um JMP zu verstehen.
> 
> ...


Du hast in dem Beispiel die Befehle numeriert, du hast es Adressen genannt. Du mußt ja irgendwo hinspringen. Wenn du den "JMP 50" Befehl generierst, dann mußt du auch eine Zeilennummer/Adresse Nr. 50 haben. Diese mußt du dann eben generieren. Oder du generierst eben ein Label an der Stelle (falls Label in der Zielsprache existieren ?)

Gruß


----------



## matrix1 (10. Mai 2010)

Hallo,
ja gut dass habe ich zum verstehen des JMP Befehls reingetan, damit man weiß wo er hinspringen soll, das kommt aber erst später, alse erstes soll er überhaupt erkennen dass da ein JMP hin muss. 
meine Ausgabe sollte so aussehen, laut meinem Compiler:


```
Eingabe:

if(x==0)
y=0;
else
y=1;
end;

Ausgabe:

If
  Id: x
  const: 0
    Assign to: y
      const: 0
       JMP  (soll natürlich zum end des if's springen, deine Idee mit der Zeilennummergenerierung ist 
                    in ordnung, so will ich es auch machen nachher)
   Assign to: y
      const: 1
```

wenn ich das hinbekomme, kümmere ich mich drum wo der JMP hinspringen muss. Was ich vorhabe ist, dass bei jeder if Anweisung, ein JMP dabi ist, dass direkt nach der ersten Anweisung bei der Ausgabe stehen soll. Deshalb meinte ich ob ich vielleicht eine neue if Anweisung definieren sollte. Danke.

Gruß


----------



## deepthroat (10. Mai 2010)

matrix1 hat gesagt.:


> Hallo,
> ja gut dass habe ich zum verstehen des JMP Befehls reingetan, damit man weiß wo er hinspringen soll, das kommt aber erst später, alse erstes soll er überhaupt erkennen dass da ein JMP hin muss.
> meine Ausgabe sollte so aussehen, laut meinem Compiler:
> 
> ...


Das ist doch aber nun wirklich trivial, im AST den entsprechenden Kindknoten eines IfK herauszusuchen und dann einfach noch JMP auszudrucken. Mach einfach mal.

Gruß


----------



## matrix1 (10. Mai 2010)

Hallo,

das ist mein IFK, der Kindknoten zu stmt_seq also child[1]=$3, 


```
IF exp stmt_seq ELSE stmt_seq END 
      { $$ = newStmtNode(IfK);
        $$->child[0] = $2;
        $$->child[1] = $3;
	$$->child[2] = $5;
	
      }
```
was genau soll ich damit machen, soll ich das in der Ausgabe definieren, da habe ich ja bereits definiert


```
case IfK:
          printf("If\n");
          break;
```

kannst du mir bitte näher erläutern was du meinst.Danke.

Gruß


----------

