Forum: PC-Programmierung Syntaktische Analyse mit Flex/Bison


von AI Z. (matrix1)


Angehängte Dateien:

Lesenswert?

Hallo.
hab seit kurzer Zeit angefamgen mit Flex/Bison zu arbeiten. hab ne 
Aufgabe leider hänge ich an einer Stelle vielleicht kann mir jemand 
weiterhelfen.

wenn man eine eine Eingabe eingibt z.B: so sieht die aus:

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

so soll der compiler jedes einzelne Element erkennen und wiedergeben, 
z.B. Es wurde ein If benutzt eine const, ein Identifier ein else, 
when.... und der Befehl JMP. Hab soweit hinbekommen, dass der compiler 
alle Eingaben erkennt, nur weiß ich nicht wie der JMP erkannt werden 
soll. JMP ist ein Jump Befehl wie bei Assembler, also falls JMP in der 
Standardeingabe eingegeben wird, dann soll ausgegeben werden, keyword: 
JMP, Assign to: L1, da in meinem Beispielcode JMP zu L1 springt. Hab 
rausgefunden, dass man in dem Baum nach dem entsprechenden Ziel-Label 
von dem JMP Befehl suchen muss oder man legt sich gleich eine Tabelle 
an, wo man einem Label gleich einen Knoten im Baum zuordnen kannst.

Leider komme ich nicht darauf, wie soll ich eine Tabelle anlegen oder 
wie frage ich ab dass ein JMP eingegeben wurde und er soll danach 
suchen. erst dachte ich da gibt es die goto funktion aber komm leider 
nicht auf die Idee.Danke für euere Hilfe.

Ich häng mal den Code an.

Hier das Syntaxtree.h file:

typedef enum {StmtK, ExpK} NodeKind;
typedef enum {IfK, RepeatK, AssignK, ReadK, WriteK, ForK, WhileK} 
StmtKind;
typedef enum {OpK, ConstK, IdK} ExpKind;

typedef struct treeNode{
  struct treeNode * child[4];
  struct treeNode * sibling;
  NodeKind nodekind;
  union {StmtKind stmt; ExpKind exp;} kind;
  union { char * op;
          int val;
          char * name;} attr;
} TreeNode;


MfG

Zafar

: Verschoben durch Admin
von Karl H. (kbuchegg)


Lesenswert?

Bei dir erzeugt ja jedes Statement einen TreeNode. Dein ganzes Programm 
ist daher im Grunde nichts anderes als ein Baum, wobei ein Baumknoten 
ein TreeNode ist.

Bei einem Label erzeugst du dir daher einen speziellen TreeNode, so wie 
du das für ein for oder ein while auch gemacht hast. Ein TreeNode für 
ein Label. Der Knoten selbst macht nichts, sondern dient nur als 
Platzhalter, so dass du innerhalb des Baumes eine Möglichkeit hast, 
einen Knoten wiederzufinden. Du willst den Namen des Labels in diesem 
Knoten speichern, denn das ist dein Suchkriterium, mit dem du den Knoten 
im Baum wiederfindest.

Bei einem JUMP machst du im ersten Durchlauf nichts. Du speicherst beim 
Jump-TreeNode einfach nur den Namen, welches Label angesprungen werden 
soll.

Die eigentliche 'Magie' des Jump passiert in einem 2-ten Durchlauf durch 
den Baum. In diesem Durchlauf gehst du den Baum komplett durch und 
bearbeitest jeden JUMP den du findest. Beim JUMP-TreeNode steht ja noch 
das Label dabei, wo hingesprungen werden soll. Mit diesem Namen gehst du 
in eine Suchroutine, die im Baum einen Label-TreeNode mit genau diesen 
Namen sucht. Findet die Suchroutine den entsprechenden Label-TreeNode so 
liefert sie dessen Adresse zurück. Diese Adresse wird dann beim Jump 
eingetragen (nach entsprechenden Prüfungen selbstverständlich).

Ein Jump ist also nichts anderes als ein TreeNode mit einem Pointer, 
wobei der Pointer auf einen anderen TreeNode im Baum zeigt.

mit Lex und Yacc hat das ganze erst mal nichts zu tun. Das ist ganz 
normale Baum-Behandlung.

Und klar. Man kann sich natürlich auch noch ein Array aufbauen, in dem 
die Labelnamen als Index dienen und man die Adresse des zugehörigen 
TreeNodes direkt ablegt. Dann vereinfacht sich die Suche. Allerdings: Da 
JUMP in einem Programm nicht allzuoft vorkommt, spielt der 
Geschwindigkeitsvorteil in der Praxis wohl kaum eine grosse Rolle. Ob 
der zusätzliche Aufwand für diese Tabelle den Laufzeitgewinn aufwiegt, 
darf für übliche Programme bezweifelt werden.

von Karl H. (kbuchegg)


Lesenswert?

Bust du sicher, dass du das so machen kannst?
1
assign_stmt: ID '=' exp
2
            { $$ = newStmtNode(AssignK);
3
              $$->child[0] = $3;
4
              $$->attr.name = $1;
5
            }

IMHO sollte das doch eher
1
assign_stmt: ID '=' exp
2
            { $$ = newStmtNode(AssignK);
3
              $$->child[0] = $3;
4
              $$->attr.name = strdup( $1 );
5
            }
sein. Ich denke nicht, dass es schlau ist, sich einen Pointer in die 
Bison interne Stringverwaltung zu merken. Aber ich bin da ehrlich gesagt 
auch nicht so bewandert, wie das funktioniert.

von AI Z. (matrix1)


Lesenswert?

Hallo,
vielen dank für deine Ausführliche Antwort, hab jetzt auch ein treeNode 
wie du gesagt hast für label und jmp gemacht, ist das etwa so in 
ordnung:

label_stmt: LABEL '(':' 'NAME')' stmt_seq END
    { $$ = newStmtNode(LabelK);
      $$->child[0] = $3;

    }

jmp_stmt: JMP '('label_stmt')' stmt_seq END
  {$$ = newStmtNode(JmpK);
  $$->child[0] = $3;
        $$->child[1] = $5;
  }

Danke.

MfG
zafar

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:

> label_stmt: LABEL '(':' 'NAME')' stmt_seq END
>     { $$ = newStmtNode(LabelK);
>       $$->child[0] = $3;
>
>     }


wieso auf einmal '(' und ')'

willst du schreiben

  L1(:)
oder willst du schreiben

  :L1

wieso gibt es da ein LABEL und ein NAME?
und was soll die stmt_seq da sein?


> jmp_stmt: JMP '('label_stmt')' stmt_seq END
>   {$$ = newStmtNode(JmpK);
>   $$->child[0] = $3;
>         $$->child[1] = $5;
>   }

Das denke ich nicht.
Bei einem Jump kannst du dir beim Parsen nur merken, wie das Label 
heisst, welches es anzuspringen gilt.

Auch stimmt die Syntax nicht. Im Programm soll doch einfach nur stehen

  JMP  L1;

Deine Syntax, die du da dem Bison unterjubeln willst, verlangt aber 
etwas ganz anderes.


(mich beschleicht schön langsam das Gefühl, dass du den am Anfang 
geposteten Parser gar nicht selbst geschrieben, sondern geklaut hast und 
in Wirklichkeit nicht so recht vestehst, was da eigentlich passiert)


Aus Sicht deines Parsers ist ein Label ganz einfach ein Statement 
(welches nicht mit einem ';' abgeschlossen ist) welches aus einem : und 
einer darauffolgenden Zeichenkette besteht.
Aus Sicht deines Parsers ist ein JUMP ganz einfach ein Statement, 
welches aus dem Schlüsselwort JUMP und einer darauffolgenden 
Zeichenkette besteht (und dem obligatorischen ';', aber der wird mit 
einer anderen Regel gefordert)

Mehr steckt da nicht dahinter. Und natürlich noch, das für die 
Zeichenketten spezielle Regeln existieren, so wie ein Variablenname ja 
uch nicht einfach nur eine Zeichenkette ist, sondern gewissen Regeln 
unterliegt.

von AI Z. (matrix1)


Lesenswert?

Hallo,

Also wenns JMP L1; heißen soll dann sollte es doch so aussehen:

jmp_stmt: JMP '('NAME',';')' stmt_seq END
  {$$ = newStmtNode(JmpK);
  $$->child[0] = $3;
        $$->child[1] = $5;
  }

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:

> jmp_stmt: JMP '('NAME',';')' stmt_seq END

Das hier sagt:
Eine Jump Anweisung besteht aus

   dem Schlüsselwort JMP
   gefolgt vom Zeichen '('
   gefolgt von einem Namen
   gefolgt von Zeichen ','
   gefolgt von einem Syntax Error (was soll der ; da sein?)
   gefolgt vom Zeichen ')'
   gefolgt von einer Anweisungskette
   gefolgt vom Schlüsselwort END


JMP L1;  erfüllt diese Bedingungen niemals!

Ein Jump Statement soll so aussehen
   JMP L1;

und genau das forderst du auch

jmp_stmt: JMP NAME

ein JMP Statement ist etwas, das mit dem Schlüsselwort JMP beginnt und 
danach kommt noch ein NAME. Fertig. Das ist ein JMP Statement.


Wenn du die Syntaxregel festlegen willst, dann musst du dich daran 
orientieren, wie du letztendes in der zu erstellenden Programmiersprache 
schreiben willst. Und das formulierst du dann als Regel. In welcher 
Reihenfolge muss was kommen, damit das alles in Summe das Geforderte 
ergibt

Wenn deine Sprache eine Anweisung haben soll

   SCHNTZLBRTZ { 8 () };

dann forderst du
  zuerst muss da SCHNTZLBRTZ stehen
  nach dem Schlüsselwort muss eine { kommen
  danach eine Zahl
  gefolgt von (
  gefolgt von )
  und als Abschluss noch }

und das schreibst du genau so hin

  schntzrtz_stm = SCHNTZLBRTZ '{' NUM '(' ')' '}'

Einfach die Aufzählung, was in welcher Reihenfolge da stehen muss, damit 
das alles in Summe ein schntzrtz_stm ergibt.

von AI Z. (matrix1)


Lesenswert?

hallo,
dann sollte mein Label auch so aussehen:

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

    }

jmp_stmt: JMP NAME
  {$$ = newStmtNode(JmpK);
  $$->child[0] = $3;
        $$->child[1] = $5;
  }

Ich habe erst seit kurzem angefangen mich mit flex/bison zu 
beschäftigen, bin sozusagen ein Anfänger auf diesem Gebiet, deshalb habe 
ich nicht soviel Ahnung, aber ich lern mit der Zeit. Danke für deine 
Hilfe.

Wenn ich den Namen des Labels ausgeben will was mache ich dann, in der 
switch anweisung im .y file, muss ich da:

          case LabelK:
          printf("  (hier NAME oder was soll hier rein)     \n");
          break;

Danke.

Gruß
zafar

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:

> Ich habe erst seit kurzem angefangen mich mit flex/bison zu
> beschäftigen,

Dann solltest du mit einfacheren Dingen als einer kompletten Sprache 
anfangen. Es gibt genügend Tutorials, die einem das auch ohne dem Besuch 
der Vorlesung 'Formale Sprachen' auf der Uni beibringen.

von AI Z. (matrix1)


Lesenswert?

Ja gut ich habe schon etliche Tutorials gelesen angewendet, kleine 
Programme geschrieben, nun ist zeit, dass ich mich den größeren Sachen 
widme, aber trotzdem kann man ja nicht alles wissen, deshalb gibt es ja 
die Foren, hänge schon lange an dieser JMP anweisung, deshalb brächte 
ich Hilfe beid er Sache.Aber Danke nochmal hast mir viel geholfen, hab 
auch einiges mehr Verstanden.

Gruß
Ali

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:
> aber trotzdem kann man ja nicht alles wissen

Na ja.
Das sind aber eigentlich Grundlagen:
Die Beschreibung eines Musters, welches in der Eingabe vorliegen muss, 
damit dieser Teil der Eingabe sich als irgendetwas qualifiziert.

Und um mehr geht es zur Zeit noch nicht:
Wie soll mein Eingabetext aussehen?
Welches Muster muss daher der Eingabetext haben?
Dieses Muster in Bison Syntax formulieren.

von AI Z. (matrix1)


Lesenswert?

Hallo,
kannst du mir in dieser Sache weiterhelfen, wäre sehr nett von dir.

Gruß
Ali

von AI Z. (matrix1)


Lesenswert?

Hallo,
wollt mal fragen ob du mir erklären könntest was die Anweisunge:

for_stmt: FOR '(' assign_stmt ',' exp ',' assign_stmt ')' stmt_seq END
    { $$ =  newStmtNode(ForK);
      $$->child[0] = $3;
      $$->child[1] = $5;
      $$->child[2] = $7;
      $$->child[3] = $9;

genau zu bedeuten hat, die erste Zeile hast mir ja in details erklärt, 
fand ich gur kannst mir erklären was die nächsten Zeilen bedeuten. hab 
diesen Code im Internet gefunden gehabt und passt sehr gut zu meiner 
Arbeit wäre gut wenn ich dsa hier auch einbißchen verstehen würde.Danke.

Gruß
Ali

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:

Ich denke du solltest noch mal deine Tutorien studieren (*), was es mit 
diesen $-Zahlen auf sich hat.

Und für den Rest: Ich mag es kaum glauben, dass sich jemand an 
Compilerbau versucht, aber mit stink normalen dynamischen 
Datenstrukturen wie Bäumen auf Kriegsfuss steht. Das legt einen Knoten 
für den Baum an und befüllt ihn mit Werten. Welche Werte? Nun, den Werte 
die den variablen Teilen in der Musterbeschreibung entsprechen und die 
Bison besorgt hat, als er beschlossen hat, dass eine Eingabezeile dem 
Muster eines for_stmt entspricht.

Das Muster besteht aus mehreren Teilen. Einige davon sind fix, andere 
sind variabel.

for_stmt: FOR '(' assign_stmt ',' exp ',' assign_stmt ')' stmt_seq END

           1   2     3         4   5   6     7         8    9

und jetzt vergleich mal

      $$->child[0] = $3;
      $$->child[1] = $5;
      $$->child[2] = $7;
      $$->child[3] = $9;

Da werden offenbar Pointer gespeichert (weil child ein Array von Pointer 
ist). In child[0] kommt ein Pointer auf das 3-te Identifizierte. Was ist 
das? Nun schau dir die Regel an. Der 3te Teil ist assign_stmt. Wenn das 
ganze ein for_stmt ist, dann muss auch assign_stmt (siehe dessen Regel) 
einen Pointer auf einen Knoten geliefert haben (bei diesem Knoten 
beginnt der Baumaufbau für diese Zuweidung). Dieser Pointer wird in 
child[0] gespeichert.

D.h. ein 'for-Anweisung' wird in einen Baum-Knoten umgesetzt. Dieser 
Baumknoten enthält 4 Pointer.
Der erste zeigt auf einen Zuweisungsknoten (der selbst wieder Kinder 
haben wird). Dieser Baumteil beschreibt die Zuweisung, die als erstes im 
for abgearbeitet werden soll.
Der zweite Pointer im for zeigt auf einen Knoten für eine Expression. 
Diese Expresion wertet die Schleifenabbruchbedingung aus.
Der dritte Pointer im for zeigt wieder auf eine Zuweisung. Offenbar die 
Zuweisung, die bei jeder Schleifeniteration durchgeführt werden soll
Und der vierte Pointer im for zeigt offenbar auf die Anweisung, die im 
Schleifenrumpf ausgeführt werden soll.

Vor mich sieht es momentan so aus, als ob du einen viel zu großen 
Brocken zu schlucken versuchst.

(*) studieren!
Nicht Abschreiben oder per Copy/Paste in deine Entwicklungsumgebung 
holen, laufen lassen, sich zurücklehnen und 'schön' sagen.
Studieren bedeutet: verstehen was im Tutorium gezeigt wird, eigene 
Versuche machen, Zusammenhänge erkennen, das verstanden geglaubte mit 
eigenen Tests überprüfen.

von Thomas B. (escamoteur)


Lesenswert?

Sag mal Karl Heinz, von was hast Du eigentlich KEINE Ahnung?
#Schwer beeindruckt.

Hab von Yaks, Bisons und den anderen Rindviehchern zum letzten mal im 
Studium gehört...

Tom

von Karl H. (kbuchegg)


Lesenswert?

Thomas Burkhart schrieb:
> Sag mal Karl Heinz, von was hast Du eigentlich KEINE Ahnung?

Alles was mit KI zu tun hat.
Neuronale Netze
Buchhaltungsprogramme :-)
...

> #Schwer beeindruckt.

"Compilerbau", "Formale Sprachen" waren meine Lieblingsvorlesungen auf 
der Uni und ich mag diesen Bereich auch heute noch sehr gerne. Auch wenn 
ich Lex/Yacc (Bison) nicht besonders gerne benutze. Ich mag rekursiven 
Abstieg lieber. Ist einfacher zu debuggen, warum die Sprachbeschreibung 
nicht so funktioniert wie vorgesehen.

von Karl H. (kbuchegg)


Lesenswert?

> Der erste zeigt auf einen Zuweisungsknoten (der selbst wieder
> Kinder haben wird). Dieser Baumteil beschreibt die Zuweisung,
> die als erstes im for abgearbeitet werden soll.
> Der zweite Pointer im for zeigt auf einen Knoten für eine
> Expression. Diese Expresion wertet die Schleifenabbruchbedingung
> aus.
> Der dritte Pointer im for zeigt wieder auf eine Zuweisung.
> Offenbar die Zuweisung, die bei jeder Schleifeniteration
> durchgeführt werden soll
> Und der vierte Pointer im for zeigt offenbar auf die Anweisung,
> die im Schleifenrumpf ausgeführt werden soll.

Etwas von der Form
1
  for( i = 5; i < 8; i = i + 3 )
2
    j = 2 * i;

baut daher diese Datenstruktur auf:
1
   +-------------------+
2
   |          forK     |
3
   | child[0]: o----------------------------------------------+
4
   | child[1]: o-----------------------------+                |
5
   | child[2]: o-----------------+           |                |
6
   | child[3]: o       |         |           |                |
7
   +-----------|-------+         |           |                |
8
               |                 |           |                v
9
               |                 |           |       +----------------+
10
               |                 |           |       |        AssignK |
11
               |                 |           |       | name: "i"      |
12
               |                 |           |       | child[0]:   o  |
13
               |                 |           |       +-------------|--+
14
               |                 |           |                     v
15
               |                 |           |       +----------------+
16
               |                 |           |       |        ConstK  |
17
               |                 |           |       | val:  5        |
18
               |                 |           |       +----------------+
19
               |                 |           v
20
               |                 |     +-------------+
21
               |                 |     |        OpK  |
22
               |                 |     | op: "<"     |
23
               |                 |     | child[0]: o------------+
24
               |                 |     | child[1]: o |          |
25
               |                 |     +-----------|-+          |
26
               |                 |                 |            v
27
               |                 |                 |  +-------------+
28
               |                 |                 |  |       IdK   |
29
               |                 |                 |  | name: "i"   |
30
               |                 |                 v  +-------------+
31
               |                 |        +-------------+
32
               |                 |        |     ConstK  |
33
               |                 |        | val: 8      |
34
               |                 |        +-------------+
35
               |                 v
36
               |         +--------------+
37
               |         |      AssignK |
38
               |         | name: "i"    |
39
               |         | child[0]:  o----------------+
40
               |         +--------------+              |
41
               |                                       v
42
               |                               +-------------+
43
               |                               |        OpK  |
44
               |                               | op: "+"     |
45
               |                               | child[0]: o-----+
46
               |                               | child[1]: o |   |
47
               |                               +-----------|-+   |
48
               |                                           |     |
49
               |                      +--------------------+     |
50
               |                      |                          |
51
               |                      v                          v
52
               |            +-------------+            +------------+
53
               |            |      ConstK |            |        IdK |
54
               |            | val: 3      |            | name: "i"  |
55
               |            +-------------+            +------------+
56
               v
57
         +--------------+
58
         |      AssignK |
59
         | name: "j"    |
60
         | child[0]: o--------------------+
61
         +--------------+                 |
62
                                          v
63
                                  +--------------+
64
                                  |          opK |
65
                                  | op: "*"      |
66
                                  | child[0]: o------------+
67
                                  | child[1]: o  |         |
68
                                  +-----------|--+         |
69
                       +----------------------+            |
70
                       |                                   |
71
                       v                                   v
72
                 +-------------+                 +-------------+
73
                 |         IdK |                 |      ConstK |
74
                 | name: "i"   |                 | val: 2      |
75
                 +-------------+                 +-------------+

PS: Deine printTree Funktion macht doch einen schön eingerückten 
Ausdruck des Baumes. Hast du dort die Einzelteile noch nicht gesehen?

von Thomas B. (escamoteur)


Lesenswert?

Du machst sowas aber nicht von Hand oder??

von AI Z. (matrix1)


Lesenswert?

Hallo,
Ich danke dir sehr, das hat mir wirklich sehr geholfen. Ich habe noch 
nie mit Flex/Bison gearbeitet, und c++ hatte ich nur gering im Studium 
ich bin eher der Hardware spezialist und nicht der 
Programmierspezialist, aber hab nun eine Aufgabe bekommen, muss nun 
programmieren, aber ich glaube ich sollte nochmal paar tutorials 
ansehen, ehrlich gesagt habe ich in keinem Tutorial was von den $ 
Zeichen gesehen gehabt. ist nicht nur so dass ich einfach schnell meine 
Arbeit abarbeiten will, will ja auch verstehen was da gemacht wird, 
deshalb frage ich ich auch an und danke, hab auch die entsprechende 
Antwort erhalten.

Gruß
Ali

von Karl H. (kbuchegg)


Lesenswert?

Thomas Burkhart schrieb:
> Du machst sowas aber nicht von Hand oder??

Doch :-)
Mit der Zeit kriegt man Übung und es geht schnell.

Ich kann nur jedem raten:
Wer mit dynamischen Datenstrukturen zu tun hat und noch nicht so die 
Übung da drinnen hat: Zeichnet mit!

Natürlich nicht mit ASCII Graphik, so wie ich hier.
Papier, ein paar unterschiedliche Buntstifte und ein Radiergummi sind 
völlig ausreichend.
So eine Zeichnung ist ein exzellentes Debugwerkzeug. Das steckt jeden 
Debugger aber locker in die Tasche, wenn es um die Aspekte: "Wo greife 
ich eigentlich zu, stimmt mein Strukturaufbau, ist die 
Manipulationsoperation in Ordnung oder fehlerhaft" geht.

von (prx) A. K. (prx)


Lesenswert?

Ali imran Zafar schrieb:

> programmieren, aber ich glaube ich sollte nochmal paar tutorials
> ansehen, ehrlich gesagt habe ich in keinem Tutorial was von den $
> Zeichen gesehen gehabt.

Dann kann's kein Tut über yacc/bison gewesen sein.

von AI Z. (matrix1)


Lesenswert?

Hallo,

Hab nun so für label und JMP geschrieben, bin aber einbißchen 
durcheinander, versteh nicht mehr was was sein soll, kannst du mir bitte 
hier weiterhelfen.Danke.


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

    }

jmp_stmt: JMP NAME
  {$$ = newStmtNode(JmpK);
  /*$$->child[0] = $1;*/
        /*$$->attr.s = strdup($2);*/
        $$->child[1] = $2;
  }

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:

> jmp_stmt: JMP NAME
>   {$$ = newStmtNode(JmpK);
>   /*$$->child[0] = $1;*/
>         /*$$->attr.s = strdup($2);*/
>         $$->child[1] = $2;
>   }

Das kann nicht sein.
Zum Zeitpunkt des Compilierens kennst du die Codestelle noch nicht, wo 
der Sprung hingehen soll. Du kennst nur den Namen des Labels.

von AI Z. (matrix1)


Lesenswert?

Hallo,

(gibt es hier eine Möglichkeit, wie es bei Assembler es gibt, Adressen 
anzufragen, z.B. könnte ich sagen, wenn JMP befehl kommt springe zu der 
oder der Adresse, das wär die Adresse wo sich label_stmt: ':' L1 
befindet
Danke.)

Hab herausgefunden, dass es ein Stack Machine gibt, dazu gibt es 
verschiedene Register, IR (Instruction Register), PC (Program Adress 
Register), AR (Activation Record Register), T (stack Top register)
dann könnte ich doch den Top Register nehmen, welches die Adresse des 
Top elements des stacks hat.


Gruß
Ali

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:
> Hallo,
>
> (gibt es hier eine Möglichkeit, wie es bei Assembler es gibt, Adressen
> anzufragen, z.B. könnte ich sagen, wenn JMP befehl kommt springe zu der
> oder der Adresse, das wär die Adresse wo sich label_stmt: ':' L1
> befindet

Du verwechselst du etwas.
Im Moment geht es darum den Baum aufzubauen.
Es geht noch nicht darum den JMP auch tatsächlich abzuarbeiten.

Und nein. Zum Zeitpunkt der Syntaxanalyse kennst du das Sprungziel nur 
dem Namen nach. Es kann ja auch erst weiter hinten im Code kommen, der 
nach gar nicht analysiert wurde.

>
> Hab herausgefunden, dass es ein Stack Machine gibt, dazu gibt es
> verschiedene Register, IR (Instruction Register), PC (Program Adress
> Register), AR (Activation Record Register), T (stack Top register)
> dann könnte ich doch den Top Register nehmen, welches die Adresse des
> Top elements des stacks hat.

Zum jetzigen Zeitpunkt alles uninteressant.
Bis du zur Statemachine kommst vergeht noch vieel Zeit. Im Moment ist 
die Syntaxanalyse drann, die eine Baumrepräsentierung des 
Eingabeprogramms erzeugt, Syntaxfehler meldet. Mehr nicht.

Danach schliesst sich dann die Phase an, in der dieser Baum auf Fehler 
abgeklopft wird, wie zb Sprungziele auf Labels, die gar nicht 
existieren.
Dann kommt die Phase in der die Variablen gesammelt werden und Adressen 
zugewiesen bekommen (je nach Datentyp).
Danach die Phase, in der die arithmetischen Ausdrücke im Baum aufgesucht 
werden und (je nachdem welche Datentypen die Sprache hat, wenn sie 
überhaupt welche hat) neue Knoten zur Datentypanpassung und Wandlung 
eingefügt werden (so nicht die Stackmaschine Instruktionen aufweist, die 
diese Anpassungen erledigen)
Daran schliesst sich die Phase an, in der einfache Optimierungen in 
diesem Baum gemacht werden, wie zb bestimmte Sequenzen durch andere zu 
ersetzen bzw. konstante Ausdrücke vorab auszurechnen und damit Teilbäume 
durch Konstanten-Knoten zu ersetzen.

(*)

Und erst dann .... wird aus der Baumrepräsentierung eine Liste von 
Anweisungen für die Stackmaschine generiert (oder die Stackmaschine 
direkt aus dem Baum heraus gefüttert). Aber so wie es aussieht, wirst du 
deine Stackmaschine nicht direkt füttern, sondern ein 'Programm' dafür 
erzeugen müssen - quasi das Assemblerprogramm, welches aus dem Baum 
entsteht und das diese spezielle Stackmaschine versteht. Und während 
dieser Generierung fällt natürlich die 'Adresse' der Instruktion ab, die 
einem Hochspachenlabel entspricht und welche dann bei allen JMP 
substituiert werden kann.

Und ehe du deinen Compiler Instruktionen für diese spezielle 
Stackmaschine generieren lässt, ist es mehr als ratsam selbst einmal ein 
paar Programme in der Maschinensprache dieser Stackmaschine zu 
schreiben. Das vermittelt dann das Wissen und auch ein gewisses Gefühl 
dafür, was der Compiler eigentlich bei bestimmten Dingen erzeugen muss, 
damit das generierte Assemblerprogramm auch wirklich dem 
Hochsprachenprogramm entspricht.

Oder so ausgedrückt: Ein Deutsch-Englisch Dolmetsch wird nicht umhin 
kommen, selbst Englisch sprechen zu können. Wer hingegen einen 
Deutsch-Englisch Dolmetsch ausbilden will (und genau in der Situation 
bist du als Compilerbauer) sollte besser fliessend Englisch sprechen. 
Das er mit dem Deutschen auch nicht auf Kriegsfuss stehen darf, versteht 
sich von selbst.


Edit: (*)
Und wahrscheinlich habe ich noch mindestens ein halbes Dutzend Passes 
durch den Baum übersehen, die aber notwendig sind, ehe die 
Codegenerierung für die Statemachine auch nur ansatzweise beginnen kann. 
Was ist zb mit Funktionsaufrufen in der Sprache? Was ist mit 
'eingebauten' Funktionen wie 'sqrt', 'sin', 'cos', etc.
All das muss behandelt werden bzw. es muss zumindest eine Vorstellung 
davon geben, wie man das behandeln will.

von Karl H. (kbuchegg)


Lesenswert?

Wer auch immer dir diese Aufgabe gegeben hat:
Schimpfe ihn einen totalen Volltrottel und gib die Aufgabe zurück.
Auch mit Lex/Bison kannst du nicht ein komplettes Vorlesungssemester in 
ein paar Tagen aufholen, in der du systematisch in die Kunst des 
Compilerbaus eingewiesen und mit praktischen Beispielen und Übungen 
begleitet wirst.
Was du da machst ist komplett sinnlos. Dir fehlt viel zu viel, als das 
es Sinn macht, da weiterzumachen.

Da du in Hardware bewandert bist:
Das ist als ob man von dir verlangen würde, den Frequenzgang in einem 
Verstärker zu begradigen, und du fängst an mit: Ich hab schon mal nach 
'Ohmschen Gesetz' gegoogelt und ich glaub ich habs auch verstanden. Aber 
wie wende ich das jetzt auf meinen Verstärker an?

von AI Z. (matrix1)


Lesenswert?

Hallo,
ja du hast eigentich schon recht, in so kurzer zeit kann ich auch nicht 
all das verstehen. Aber um meine Aufgabe zu beenden muss ich nur noch 
diesen einen JMP befehl genereieren, sonst funktioniert der Rest, kannst 
du mir bitte nicht dabei weiterhelfen dies zu ende zu bringen, ich 
glaube ich bin an einem Punkt angelangt, wo ich nicht weiter kommen 
werde, da wie du schon gesagt hast, dass wissen fehlt, es wäre super, 
wenn du mir hier weiterhelfen könntest.Danke.

Gruß
Ali

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:

> diesen einen JMP befehl genereieren, sonst funktioniert der Rest, kannst
> du mir bitte nicht dabei weiterhelfen dies zu ende zu bringen,

Das interessante dabei ist:
Ich hab dir schon mindestens 3 mal gesagt, was es bei einem JMP während 
des Syntaxscannes zu tun gibt. Einfach den Namen des Labels, welches 
angesprungen werden soll, wegspeichern. Dazu hast du im TreeNode ein 
schänes name Feld, welches sich dafür anbietet.

Ich denke, das waren genügend Hinweise. Noch deutlicher kann ich gar 
nicht sein, aussser das ich schreibe, ein JMP wird in dieser Phase des 
Compilers so behandelt, da das das Einzige ist, was du zum jetzigen 
Zeitpunkt (also während das Syntaxscannens) tun kannst:

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

aber das Schreib ich ja nicht.

(Und bei einem Label spricht auch nichts dagegen, den Labelnamen im name 
Feld abzulegen und nicht in s. Bei
  :L1
kann man L1 durchaus als 'den Namen des Labels' auffassen.)

von Rene B. (themason) Benutzerseite


Lesenswert?

@karl-heinz

Danke für das erneute Auffrischen meiner Compilerbau-Vorlesung von vor 
12 Jahren :-)) Ich hatte zwar (soweit meine verstaubten Zellen noch 
irgendwelche Zuckungen an Erinnerungen dieser Zeit von sich geben) nur 
den Syntaktischen Teil gehabt (also nur Tokenizer und Parser, aber auch 
mit Tools wie Bison/Lex) aber war davon sehr angetan und versuche mir 
seit dem immer mal wieder nen Compiler zu schreiben :-))
Ich denke mittlerweile habe ich dazu schon genügend Kenntnisse (selbst 
wenn ich keine Tools wie Bison/Yacc/Lex/usw verwende).

Da mal direkt eine Frage zu ...
Gibt es ein Beispiel *.l und *.y File in dem die Struktur der Sprache C 
komplett enthalten ist ? (ich brauche nur die syntaktische Auflistung)
Also so ähnliche Statements wie Oben mit "Name = Aufbau END { 
Wegspeichern } ...". In EBNF müsst ich mich auch erst wieder 
einarbeiten.
Und wenn es so beschrieben ist wie oben ist es einfacher lesbar.

Ich habe ja (mehrere) einfache Parser geschrieben, und als eines der 
erklärten Ziele möchte ich zum einen einen Interpreter schreiben (auf 
Basis meines Parsers, evtl mit Byte-Zwischencode) und zum anderen möchte 
ich mich nun endlich mal an einen C-Compiler wagen. Selbst wenn ich 
erstmal "nur" den Text syntaktisch überprüfe und mir eine Baumstruktur 
daraus generieren lasse um mir dann Informationen über das Programm zu 
generieren (welche Funktion ist in welchem Modul, usw)
Aber dazu müsste ich die komplette Syntax (am liebsten dann in der 
Bison/Lex-Schreibweise) haben um Teile dann davon mit meinem Parser 
umsetzen zu können.
Ist vllt ein bissl gewagt bzw hoch gesteckt, aber wie heißt es so schön 
: "Meet the challenge" :-)).
Und ich denke vom Prinzip her müsste sich das so machen lassen wie ich 
mir das Vorstelle mit meinem Parser.

von (prx) A. K. (prx)


Lesenswert?

> Gibt es ein Beispiel *.l und *.y File in dem die Struktur der Sprache C
> komplett enthalten ist ?

http://pcc.zentus.com/cgi-bin/cvsweb.cgi/cc/ccom/cgram.y?rev=1.280;content-type=text%2Fplain
http://pcc.zentus.com/cgi-bin/cvsweb.cgi/cc/ccom/scan.l?rev=1.90;content-type=text%2Fplain

Den Rest vom Compiler gibts unter http://pcc.ludd.ltu.se. Der PCC ist 
viel einfacher als der GCC, folglich weit besser geeignet um mal einen 
Blick hinein zu werfen.

von Karl H. (kbuchegg)


Lesenswert?

Rene Böllhoff schrieb:

> Da mal direkt eine Frage zu ...
> Gibt es ein Beispiel *.l und *.y File in dem die Struktur der Sprache C
> komplett enthalten ist ?

Müsste es irgendwo im Web geben.
Wenn nicht, hol dir die gcc-Sourcen (oder einen anderen freien 
Compiler). Ich denke, die benutzen Lex/Yacc.

Das Problem an der C-Syntax: Sie ist nicht LL1 und die Umformung in LL1 
ist auc nicht wirklich trivial. D.h. mit nur einem Token Vorschau kann 
man nicht in allen Fällen entscheiden, wie es weitergeht. Damit ist ein 
gewöhnlicher rekursiver Abstieg so ohne weiteres nicht möglich. Der Yacc 
kommt aber out of the Box damit klar.

Google Stichwörter wären IMHO
C grammer yacc
Damit, oder Variationen davon, sollte sich was finden lassen.

Bingo:
erster Treffer
http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
(ok, 1985 ist schon alt)

Der hier sieht auch gut aus: 
http://www.thefreecountry.com/sourcecode/grammars.shtml

von (prx) A. K. (prx)


Lesenswert?

Karl heinz Buchegger schrieb:

> Wenn nicht, hol dir die gcc-Sourcen

Der nicht. Früher hatte GCC mal Bison verwendet, aber seit GCC wirklich 
brauchbare Fehlermeldungen bei syntaktischen Fehlern auswirft tut er das 
nicht mehr.

von Rene B. (themason) Benutzerseite


Lesenswert?

@A.K. und Karl Heinz

Erstmal danke für die Links und Infos. Das das ganze nicht so ganz 
trivial ist ist mir klar :-)). Geht sich auch erstmal nur um einen 
Versuch ob ich das mit meinem Parser gestemmt bekomme. Dadurch das sich 
der Parser sehr leicht rekursiv gestalten lässt sollte man damit was 
Programmiersprachen angeht einige Möglichkeiten haben. Daher auch die 
Erwähnung des Interpreters. Bei einer entsprechen einfach gehaltenen 
Programmiersprache müsste sich sowas mit dem Parser (nur erstmal die 
syntaktische Seite) an ein paar Nachmittagen realisieren lassen.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Karl heinz Buchegger schrieb:
>
>> Wenn nicht, hol dir die gcc-Sourcen
>
> Der nicht. Früher hatte GCC mal Bison verwendet, aber seit GCC wirklich
> brauchbare Fehlermeldungen bei syntaktischen Fehlern auswirft tut er das
> nicht mehr.

Ah. ok. Danke
Hab mir die gcc Sourcen vor 20-jahren mal geholt, reingeguckt, 
entschieden dass ich keinen blassen Schimmer habe, wie das funktioniert 
und ... runtergelöscht.

Ja, ja. Das leidige Thema Fehlermeldungen.

von Karl H. (kbuchegg)


Lesenswert?

Rene Böllhoff schrieb:

> Erwähnung des Interpreters. Bei einer entsprechen einfach gehaltenen
> Programmiersprache müsste sich sowas mit dem Parser (nur erstmal die
> syntaktische Seite) an ein paar Nachmittagen realisieren lassen.

Bei einer einfach gehaltenen Programmiersprache ist das kein Thema. Mit 
ein wenig Übung geht das flott.

Ich nehm gern den COCO/R. Hauptsächlich deshalb, weil das Teil an meiner 
Alma Mater entwickelt wurde und ich gut damit klar komme, dass ein 
rekursiver Abstieg erzeugt wird.

Dazu dann noch eine Variablenverwaltung und eine Stackmaschine.
Ich mach mir die Sache meistens einfach: So wie bei Ur-Pascal muss alles 
in einem File sein. Damit brauch ich keinen ausgefuchsten Linker und 
Funktionsaufrufe sind einfach umzusetzen (sofern ich Funktionsaufrufe 
überhaupt vorsehe). Auch specke ich oft beim Scoping von Variablen etwas 
ab (alles ist global :-). Kommt halt immer drauf an, was der geplante 
Einsatzzweck der Sprache ist und was ich so an typischen Programmgrößen 
erwarte.

von Rene B. (themason) Benutzerseite


Lesenswert?

>So wie bei Ur-Pascal muss alles in einem File sein.

Das wäre/ist auch mein bevorzugter Ansatz für einen ersten Interpreter. 
Vor allem lässt sich dann (je nach Umfang der Sprache) das ganze "mal 
eben" auf einen AVR portieren.
Interessant wäre auch (vllt später als Erweiterung) das ganze von einer 
SD-Karte online Interpretieren zu lassen. Dann könnte man noch u.u. 
zusätzliche Module (also mehrere Programm-Dateien) laufen lassen. Mal 
schauen was mir da noch für Schweinereien einfallen :-))

Aber COCO/R sagt mir nichts. Müsst ich mir mal anschauen. Hört sich 
interessant an.

von AI Z. (matrix1)


Angehängte Dateien:

Lesenswert?

Hallo,
hab nun weitere Sachen geändert, waren einige Fehler drin, habs erst 
später gemerkt, das ich in der syntaxtree.h file noch die LabelK und 
JmpK eintragen muss, aber leider kommen immer noch zwei Feher:

JMP Undeclared (first use in function)
NAME undeclared (...........)

die sind soch bereits definiert warum kommt dann diese Fehlermeldung.
Danke für deine Hilfe.

Ich häng mal die neuen dateien.

Gruß
Ali

von AI Z. (matrix1)


Lesenswert?

Hallo,
hab den Fehler gefunden jtzt funktioniert das programm, hatte vergessen 
das .tab.h file umzubenennen.

danke für deine Hilfe und deine Geduld, bei Fragen melde ich mich 
wieder.
Einen schönen Tag noch.

MfG
Ali

von Karl H. (kbuchegg)


Lesenswert?

> jtzt funktioniert das programm

Das glaub ich nicht

1
label_stmt: ':' NAME 
2
    { $$ = newStmtNode(LabelK);
3
      $$->child[0] = $2;
4
5
    }
6
7
jmp_stmt: JMP NAME
8
  {$$ = newStmtNode(JmpK);
9
  $$->attr.name = strdup($2);

Fällt dir was auf?
Das eine mal behandelst du einen Namen, indem du ihn als child in den 
Baum einhängst, das andere mal, in dem du dir einen Pointer auf den 
String in attr.name merkst.

Ja, wie ist das nun bei Namen? Sind das tatsächlich Child Knoten?

Dazu kommt noch
1
  case LabelK:
2
          printf("Label: %s\n",tree->attr.name);
3
          break;
4
  case JmpK:
5
          printf("JMP\n");
6
          break;

Aha. Bei einem Label, hast du zwar den Labelnamen im Child Knoten 
gespeichert (hat denn dein Compiler gar nichts dazu gesagt?), die 
Ausgabe machst du aber vom attr.name Feld.
Beim Jump wird (sicherheitshalber) erst mal gar nichts ausgegeben.


Ich würde sagen: von funktionieren bist du noch weit entfernt.
Dein Programm geht vielleicht durch den Compiler (wobei es allerdings 
Warnungen geben müsste. Auch in C kann man nicht straflos einen char 
Pointer an einen TreeNode Pointer zuweisen), aber funktionieren tut es 
nicht.

von AI Z. (matrix1)


Lesenswert?

Hallo,
hab das programm ausgeführt, läuft auch wie gehabt, leider funktioniert 
das nicht ganz mit dem JMP befehl. Kannst du mir einen weiteren rat 
geben was noch fehlt, oder mache ich da einen Gedankenfehler.

Gruß
Ali

von AI Z. (matrix1)


Lesenswert?

Hallo,
also der Compiler hat ga rnichts gesagt und es gab auch keine Warnung, 
na gut dachte jetzt sollte es funktionieren hat es aber leider nicht 
getan.

von Karl H. (kbuchegg)


Lesenswert?

Und das Chaos mit der Speicherung von Strings hast du auch noch nicht 
nahcgeschlagen, bzw. bereinigt

Aus der FAQ
1
11.3 Strings are Destroyed
2
     My parser seems to destroy old strings, or maybe it loses track of
3
     them.  Instead of reporting ‘"foo", "bar"’, it reports
4
     ‘"bar", "bar"’, or even ‘"foo\nbar", "bar"’.
5
6
This error is probably the single most frequent “bug report” sent to Bison lists, but is only concerned with a misunderstanding of the role of the scanner. Consider the following Lex code: 
7
8
%{
9
#include <stdio.h>
10
char *yylval = NULL;
11
%}
12
%%
13
.*    yylval = yytext; return 1;
14
\n    /* IGNORE */
15
%%
16
int
17
main ()
18
{
19
  /* Similar to using $1, $2 in a Bison action.  */
20
  char *fst = (yylex (), yylval);
21
  char *snd = (yylex (), yylval);
22
  printf ("\"%s\", \"%s\"\n", fst, snd);
23
  return 0;
24
}
25
26
If you compile and run this code, you get: 
27
28
     $ flex -osplit-lines.c split-lines.l
29
     $ gcc  -osplit-lines   split-lines.c -ll
30
     $ printf 'one\ntwo\n' | ./split-lines
31
     "one
32
     two", "two"
33
34
this is because yytext is a buffer provided for reading in the action, but if you want to keep it, you have to duplicate it (e.g., using strdup).


Aha, Hatte ich doch wieder mal den richtigen Riecher.

Strings müssen mittels strdup dupliziert werden. Du bekommst immer nur 
Pointer auf Strings, die temporär sind.

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:
> Hallo,
> hab das programm ausgeführt, läuft auch wie gehabt,

Das y-File, das du gepostet hast, KANN nicht funktionieren
1
label_stmt: ':' NAME 
2
    { $$ = newStmtNode(LabelK);
3
      $$->child[0] = $2;
Hier speicherst du einen Pointer auf den Namen in child[0].

Für die Ausgabe ...
1
  case LabelK:
2
          printf("Label: %s\n",tree->attr.name);
... benutzt du aber den attr.name Pointer.

Das KANN nicht funktionieren. Da brauch ich das noch nicht einmal 
compilieren und testen um das zu sehen.
Wenn man ein Zwischenergebnis einer Variablen zuweist, dieses 
Zwischenergebnis dann von einer ganz anderen Variablen auszulesen 
versucht, dann KANN da niemals der richtige Wert rauskommen.

(Und Hinweis: attr.name wäre richtig gewesen)

von Karl H. (kbuchegg)


Lesenswert?

Ali imran Zafar schrieb:


> Kannst du mir einen weiteren rat
> geben was noch fehlt, oder mache ich da einen Gedankenfehler.

Das Problem ist, das es bei deinem Kentnissstand mit einem Rat oder Tip 
nicht getan ist.

Ich denke bereits jetzt mit Schaudern an die Funktion (die du noch nicht 
hast), die im Baum nach einem Label sucht um dann letztendlich die Jumps 
auflösen zu können. Das wird eine rekursive Funktion werden und ob ich 
dir die in verdauliche Brocken aufdröseln kann, weiß ich ehrlich gesagt 
noch nicht.

von AI Z. (matrix1)


Lesenswert?

Hallo,

wollt mal fragen, label ist doh ein Nichtterminalsymbol, folglich 
brauche ich doch kein extra Token NAME, label besteht doch aus einem 
doppelpunkt und Bezeichner, also ':' ID sollte doch reichen.Danke.

Gruß
Ali

von AI Z. (matrix1)


Lesenswert?

So nach langem suchen und viel lesen bin ich zu diesem schluss gekommen:

in lex:

":" {return yytext[0];}

in yacc:

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

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

ist das so ungefähr in ordnung,

aber leider kommt eine warnung:
nonterminal useless in grammar: label_stmt
1 rule useless in grammar: label_stmt: ':' ID

was hat das zu bedeuten.danke.

Gruß
Ali

von AI Z. (matrix1)


Lesenswert?

Guten Morgen,
ich muss da was korrigieren da ist noch ein kleiner Fehler:

in lex:

":" {return yytext[0];}

in yacc:

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

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

so kompiliert er ohne Fehler.Danke.
Gruß
Ali

von AI Z. (matrix1)


Lesenswert?

Hallo,
ich habe jetzt alles hinbekommen und hab auch weitere sachen eingefügt 
wie operatoren: >=, <=, != und logische Operatoren and, or.
Nun bin ich dabei die Inkrement und dekrement Operatroen zu deklarieren, 
wenn ich in der Eingabe ++ eingebe dann klappt auch alles wuderbar gibt 
auch aus INC wurde benutzt, nun will ich, das wenn "++x" eingegeben 
wird, dass dann ausgegeben wird:

INC
   Id:x

aber der compiler erkennt x nicht, ich habe so definiert, wie bei dem 
JMP Befehl, aber leider geht das nicht, habs auch probiert mit
"++"{return yytext[0];} klappt leider auch nicht, wäre nett wenn du mir 
da helfen könntest, hab die aktuellste files in 
http://bitbucket.org/matrix/changed-tiny aktualisiert.Danke.

Gruß
Ali

von Sidra K. (Firma: Education) (skhalid)


Lesenswert?

hi,

I m newbie to flex-bison. I found this post very helpful with respect to 
learning. I am using compiler.y and compiler.l from the below links.
flex-bison.http://bitbucket.org/matrix/changed-tiny

If i use this input to parse
a = 5;
b = 6;
print(a);
scan(b);
compiler.y works fine and output the parse tree.

I am facing the problem to parse the if condition in the above 
compiler.y
when But i run this input

a = 5;
b = 6;
if(a <=5 )
a = b;
end

it gives the syntax error on line 3 for if statement. Compiler.y is not 
parsing the if condition.I am unable to figure out if there is some 
thing wrong with input or grammar compiler.y. Same is the case for 
while/for statements.
Please share sample input file to parse the whole grammar so that i can 
debug and run compiler or there is something incorrect with grammar.
Please help. Thanks in advance

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.