/// <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); } }
/// <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(); } }