Ejemplo n.º 1
0
 /// <summary>
 /// Generam toate metodele de care avem nevoie pe baza tabelului de analiza sintactica.
 /// </summary>
 /// <param name="tabel">Tabelul de analiza sintactica.</param>
 private void GenereazaMetodeIndividuale(TAS tabel, List <string> terminale)
 {
     //Pentur fiecare linie din tabel cream cate o metoda care sa rezolve cerintele analizorului.
     foreach (var linie in tabel.Linii.Distinct())
     {
         //Cream metoda curenta.
         CodeMemberMethod memberMethod = new CodeMemberMethod
         {
             //Setam numele metodei.
             Name = linie.Linie,
             //Setam ceea ce returneaza.
             ReturnType = new CodeTypeReference(typeof(void)),
             //Setam atributele metodei.
             Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static
         };
         //Adaugam codul din cadrul metodei.
         CodeSnippetExpression codeExpression = new CodeSnippetExpression();
         bool firstAttempt = true;
         foreach (var simbol in linie.Valori)
         {
             if (!firstAttempt)
             {
                 codeExpression.Value += "\t\t\t";
             }
             codeExpression.Value += $"if(input[pozitie] == \"{simbol.Key}\") {{\n";
             //Analizam codul dupa urmatoarele posibilitati:
             foreach (var rightSideSymbol in simbol.Value.RightSide)
             {
                 //Daca primul simbol din partea dreapta a regulii este terminal
                 //ne deplasam mai departe in input.
                 if (terminale.Contains(rightSideSymbol))
                 {
                     codeExpression.Value += "\t\t\t\tpozitie++;\n";
                 }
                 else
                 {
                     //Atlfel apelam metoda corespunzatoare urmatorului neterminal.
                     codeExpression.Value += $"\t\t\t\t{rightSideSymbol}();\n";
                 }
             }
             //Daca avem regula care in partea dreapta il contine pe eps
             //il vom trece direct la return;.
             codeExpression.Value += "\t\t\t\treturn;\n\t\t\t}\n";
             firstAttempt          = false;
         }
         //Daca nu gasim ceea ce cautam aruncam o eroare.
         codeExpression.Value += $"\t\tthrow new Exception($\"Error at {memberMethod.Name}. Input given: {{input[pozitie]}}. Expected something else.\")";
         memberMethod.Statements.Add(new CodeExpressionStatement(codeExpression));
         codeMethods.Add(memberMethod);
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Metoda pentru generarea fisierului sursa care contine
        /// analizorul LL1 pentru gramatica data ca aplicatie consola.
        /// </summary>
        /// <param name="fileName">Numele fisierului.</param>
        /// <param name="tabel">Tabelul de analiza sintactica.</param>
        public void GenereazaCodSursa(string fileName, TAS tabel, List <string> terminale)
        {
            //Ne folosim de libraria CodeDOM.
            //Cream un CodeCompileUnit care sa contina graful programului.
            CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
            //Declaram un namespace pentru aplicatie (numele fisierului).
            CodeNamespace codeNamespace = new CodeNamespace(Path.GetFileNameWithoutExtension(Path.GetFileName(fileName)));

            //Adaugam namespace-ul create unitatii de compilare.
            codeCompileUnit.Namespaces.Add(codeNamespace);
            //Adaugam namespace-ul System.
            codeNamespace.Imports.Add(new CodeNamespaceImport("System"));
            codeNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            //Adaugam clasa Program, pe care o adaugam si tipurilor de date din namespace-ul creat.
            CodeTypeDeclaration classProgram = new CodeTypeDeclaration("Program");

            codeNamespace.Types.Add(classProgram);

            //Generam toate metodele de care avem nevoie.
            GenereazaMetodeIndividuale(tabel, terminale);
            //Le adaugam in clasa noastra.
            classProgram.IsClass = true;
            classProgram.Members.AddRange(codeMethods.ToArray());
            //Adaugam campul pentru input.
            classProgram.Members.Add(new CodeMemberField(new CodeTypeReference(typeof(List <string>)), "input")
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static
            });
            //Adaugam campul pentru pozitie.
            classProgram.Members.Add(new CodeMemberField(new CodeTypeReference(typeof(System.Int32)), "pozitie")
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static
            });

            //Declaram un nou punct de intrare in program.
            CodeMemberMethod mainMethod = GenereazaMetodaMain(tabel.Linii[0].Linie);

            //O adaugam la clasa.
            classProgram.Members.Add(mainMethod);

            //Generam fisierul .cs.
            CSharpCodeProvider provider = new CSharpCodeProvider();

            using (StreamWriter sw = new StreamWriter(fileName, false))
            {
                IndentedTextWriter tw = new IndentedTextWriter(sw, "\t");
                provider.GenerateCodeFromCompileUnit(codeCompileUnit, tw, new CodeGeneratorOptions());
                tw.Close();
            }
        }