//Синтаксический анализ кода public bool GoAnalyze() { if (Code.SyntError != "none") return false; Gramma.Init(); #if DEBUG Gramma.Check(); #endif Configuration config = new Configuration(); //История конфигураций Stack<Configuration> history = new Stack<Configuration>(); history.Push(config); while (true) //додумать условие цикла { //Отношение перехода делаем на токенах if (config.s == 'q') { if (config.L2.Count != 0) { //1 пункт отношения, "На верху L2 не терминал, растим дерево" if (!config.L2.Peek().term) { Configuration.elem item = new Configuration.elem(config.L2.Pop()); Pravilo current = Gramma.p.Find(x => x.leftSide == item.value); //текущее правило if (item.value != "string") //првоеряю не ожидалась ли строка { if (item.value != "chislo" && item.value != "integer" && item.value != "real") { if (item.value != "id") { config.L1.Push(new Configuration.elem(current.leftSide, false, 1));//в магазин L1 суём левую часть правила for (int altIndex = current.rightSide[0].Count - 1; altIndex >= 0; altIndex--)//суём первую альтернативу в магазин L2 по элементно { if (current.rightSide[0][altIndex].notTerminal != "") { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].notTerminal, false, 1)); } else { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].terminal, true, 1)); } } } else { //Успешное прохождение идентификатора if (Code.Tokens[config.i].klass == "идентификатор") { config.L1.Push(new Configuration.elem(current.leftSide, false, 1)); config.L2.Push(new Configuration.elem(Code.Tokens[config.i].value, true, 1)); } else { config.L1.Push(new Configuration.elem(current.leftSide, false, 1));//в магазин L1 суём левую часть правила for (int altIndex = current.rightSide[0].Count - 1; altIndex >= 0; altIndex--)//суём первую альтернативу в магазин L2 по элементно { if (current.rightSide[0][altIndex].notTerminal != "") { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].notTerminal, false, 1)); } else { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].terminal, true, 1)); } } } } } else { //Успешное прохождение числа if (Code.Tokens[config.i].klass == "число ") { if (Code.Tokens[config.i].type == "real") { config.L1.Push(new Configuration.elem(current.leftSide, false, 2)); config.L2.Push(new Configuration.elem(Code.Tokens[config.i].value, true, 2)); } else { config.L1.Push(new Configuration.elem(current.leftSide, false, 1)); config.L2.Push(new Configuration.elem(Code.Tokens[config.i].value, true, 1)); } } else { /* Code.SyntError = "В строке " + Code.Tokens[config.i].str_num + " столбце " + Code.Tokens[config.i].pos_num + " ожидалось число"; return false; */ config.L1.Push(new Configuration.elem(current.leftSide, false, 1));//в магазин L1 суём левую часть правила for (int altIndex = current.rightSide[0].Count - 1; altIndex >= 0; altIndex--)//суём первую альтернативу в магазин L2 по элементно { if (current.rightSide[0][altIndex].notTerminal != "") { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].notTerminal, false, 1)); } else { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].terminal, true, 1)); } } } } } else { //Успешное прохождение строки if (Code.Tokens[config.i].klass == "строка") { config.L1.Push(new Configuration.elem(current.leftSide, false, 1)); config.L2.Push(new Configuration.elem(Code.Tokens[config.i].value, true, 1)); } else { /* Code.SyntError = "В строке " + Code.Tokens[config.i].str_num + " столбце " + Code.Tokens[config.i].pos_num + " ожидалась строка"; return false; */ config.L1.Push(new Configuration.elem(current.leftSide, false, 1));//в магазин L1 суём левую часть правила for (int altIndex = current.rightSide[0].Count - 1; altIndex >= 0; altIndex--)//суём первую альтернативу в магазин L2 по элементно { if (current.rightSide[0][altIndex].notTerminal != "") { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].notTerminal, false, 1)); } else { config.L2.Push(new Configuration.elem(current.rightSide[0][altIndex].terminal, true, 1)); } } } } history.Push(config); } //2 пункт отношения, "На верху L2 терминал сравниваем входной токен" else { if (config.i < Code.Tokens.Count) { Configuration.elem item = new Configuration.elem(config.L2.Peek()); //"Успешное сравнение" if ((Code.Tokens[config.i].value == item.value) || (item.value == "lambda")) { if ((warn != null) && (warn.id < config.i)) { //Убираем подозрительный токен warn = new Warning(); } config.L2.Pop(); config.L1.Push(item); if (item.value != "lambda") config.i++; } //4 пункт отношения. Не успешное сравнение else { //Сохраняем подозрительный токен if (warn.id < config.i) { warn = new Warning(); warn.nTerm = config.L1.Peek(); warn.term = item; warn.id = config.i; } config.s = 'b'; } } else { Code.SyntError = "Неожиданный конец файла"; return false; } history.Push(config); } } else { //3 пункт отншения. Успешное завершение if (config.i == Code.Tokens.Count) { config.s = 't'; config.L2.Push(new Configuration.elem("lambda", true, 0)); history.Push(config); Code.conclusion = config.Seq(); return true; } else { ErrorForm(warn); //Code.SyntError = "Неожиданный конец файла"; return false; } } } else { if (!config.L1.Peek().term) //6. Испытание очередной альтернативы { //тестовый костыль if (!config.L2.Peek().term || !(config.L1.Peek().value == "id")) { Configuration.elem item = new Configuration.elem(config.L1.Pop()); Pravilo current = Gramma.p.Find(x => x.leftSide == item.value); //текущее правило if (current.rightSide.Count > item.altIndex) //a. замена альтернативы если существует следующая альтернатива { for (int elemIndex = 0; elemIndex < current.rightSide[item.altIndex - 1].Count; elemIndex++) { if (config.L2.Count != 0) { config.L2.Pop(); } else { ErrorForm(warn); return false; } } for (int elemIndex = current.rightSide[item.altIndex].Count - 1; elemIndex >= 0; elemIndex--)//суём j+1 альтернативу в магазин L2 по элементно { if (current.rightSide[item.altIndex][elemIndex].notTerminal != "") { config.L2.Push(new Configuration.elem(current.rightSide[item.altIndex][elemIndex].notTerminal, false, item.altIndex + 1)); } else { config.L2.Push(new Configuration.elem(current.rightSide[item.altIndex][elemIndex].terminal, true, item.altIndex + 1)); } } item.altIndex++; config.L1.Push(item); config.s = 'q'; } else { if (config.i == 0 && item.value == "main") //б. прекращение разбора { ErrorForm(warn); //Code.SyntError = "Цепочка не принадлежит языку"; return false; } else //в. Отмена результата { for (int elemIndex = 0; elemIndex < current.rightSide[item.altIndex - 1].Count; elemIndex++) { config.L2.Pop(); } config.L2.Push(new Configuration.elem(item.value, false, 1)); } } } else { config.L2.Pop(); config.L2.Push(new Configuration.elem(config.L1.Pop().value, false, 1)); } } else //5 Возврат по ходу { Configuration.elem item = new Configuration.elem(config.L1.Pop()); config.L2.Push(item); //config.L2.Push(config.L1.Pop()); //на будующее когда всё будет работать if (item.value != "lambda") config.i--; } history.Push(config); } } }