static tType StFunc(int F) { switch (F) { case spABS: IntExpression(); Gen.Abs(); return(tType.Int); case spMAX: ParseType(); Gen.Cmd(int.MaxValue); return(tType.Int); case spMIN: ParseType(); Gen.Min(); return(tType.Int); case spODD: IntExpression(); Gen.Odd(); return(tType.Bool); } return(tType.None); // Чтоб не было предупреждений }
// Имя {"(" Выраж | Тип ")"} | Число | "(" Выраж ")" static tType Factor() { Obj X; tType T = tType.None; if (Scan.Lex == tLex.lexName) { if ((X = Table.Find(Scan.Name)).Cat == tCat.Var) { Gen.Addr(X); //Адрес переменной Gen.Cmd(OVM.cmLoad); Scan.NextLex(); return(X.Type); } else if (X.Cat == tCat.Const) { Gen.Const(X.Val); Scan.NextLex(); return(X.Type); } else if (X.Cat == tCat.StProc && X.Type != tType.None) { Scan.NextLex(); Check(tLex.lexLPar, "\"(\""); T = StFunc(X.Val); Check(tLex.lexRPar, "\")\""); } else { Error.Expected( "переменная, константа или процедура-функции" ); } } else if (Scan.Lex == tLex.lexNum) { Gen.Const(Scan.Num); Scan.NextLex(); return(tType.Int); } else if (Scan.Lex == tLex.lexLPar) { Scan.NextLex(); T = Expression(); Check(tLex.lexRPar, "\")\""); } else { Error.Expected("имя, число или \"(\""); } return(T); }
// ["+"|"-"] Слагаемое {ОперСлож Слагаемое} static tType SimpleExpr() { tType T; tLex Op; if (Scan.Lex == tLex.lexPlus || Scan.Lex == tLex.lexMinus) { Op = Scan.Lex; Scan.NextLex(); if ((T = Term()) != tType.Int) { Error.Expected("выражение целого типа"); } if (Op == tLex.lexMinus) { Gen.Cmd(OVM.cmNeg); } } else { T = Term(); } if (Scan.Lex == tLex.lexPlus || Scan.Lex == tLex.lexMinus) { if (T != tType.Int) { Error.Message( "Несоответствие операции типу операнда" ); } do { Op = Scan.Lex; Scan.NextLex(); if ((T = Term()) != tType.Int) { Error.Expected("выражение целого типа"); } switch (Op) { case tLex.lexPlus: Gen.Cmd(OVM.cmAdd); break; case tLex.lexMinus: Gen.Cmd(OVM.cmSub); break; } } while(Scan.Lex == tLex.lexPlus || Scan.Lex == tLex.lexMinus); } return(T); }
// Переменная "=" Выраж static void AssStatement() { Variable(); if (Scan.Lex == tLex.lexAss) { Scan.NextLex(); IntExpression(); Gen.Cmd(OVM.cmSave); } else { Error.Expected("\":=\""); } }
static void WhileStatement() { int WhilePC = Gen.PC; Check(tLex.lexWHILE, "WHILE"); BoolExpression(); int CondPC = Gen.PC; Check(tLex.lexDO, "DO"); StatSeq(); Check(tLex.lexEND, "END"); Gen.Cmd(WhilePC); Gen.Cmd(OVM.cmGOTO); Gen.Fixup(CondPC); }
// MODULE Имя ";" [Импорт] ПослОбъявл [BEGIN ПослОператоров] // END Имя "." static void Module() { Obj ModRef; //Ссылка на имя модуля в таблице Check(tLex.lexMODULE, "MODULE"); if (Scan.Lex != tLex.lexName) { Error.Expected("имя модуля"); } //Имя модуля - в таблицу имен ModRef = Table.NewName(Scan.Name, tCat.Module); Scan.NextLex(); Check(tLex.lexSemi, "\";\""); if (Scan.Lex == tLex.lexIMPORT) { Import(); } DeclSeq(); if (Scan.Lex == tLex.lexBEGIN) { Scan.NextLex(); StatSeq(); } Check(tLex.lexEND, "END"); //Сравнение имени модуля и имени после END if (Scan.Lex != tLex.lexName) { Error.Expected("имя модуля"); } else if (Scan.Name != ModRef.Name) { Error.Expected( "имя модуля \"" + ModRef.Name + "\"" ); } else { Scan.NextLex(); } if (Scan.Lex != tLex.lexDot) { Error.Expected("\".\""); } Gen.Cmd(0); // Код возврата Gen.Cmd(OVM.cmStop); // Команда останова Gen.AllocateVariables(); // Размещение переменных }
static void IfStatement() { int CondPC; int LastGOTO; Check(tLex.lexIF, "IF"); LastGOTO = 0; //Предыдущего перехода нет BoolExpression(); CondPC = Gen.PC; //Запомн. положение усл. перехода Check(tLex.lexTHEN, "THEN"); StatSeq(); while (Scan.Lex == tLex.lexELSIF) { Gen.Cmd(LastGOTO); //Фиктивный адрес, указывающий Gen.Cmd(OVM.cmGOTO); //на место предыдущего перехода LastGOTO = Gen.PC; //Запомнить место GOTO Scan.NextLex(); Gen.Fixup(CondPC); //Зафикс. адрес условного перехода BoolExpression(); CondPC = Gen.PC; //Запомн. положение усл. перехода Check(tLex.lexTHEN, "THEN"); StatSeq(); } if (Scan.Lex == tLex.lexELSE) { Gen.Cmd(LastGOTO); //Фиктивный адрес, указывающий Gen.Cmd(OVM.cmGOTO); //на место предыдущего перехода LastGOTO = Gen.PC; //Запомнить место последнего GOTO Scan.NextLex(); Gen.Fixup(CondPC); //Зафикс. адрес условного перехода StatSeq(); } else { Gen.Fixup(CondPC); //Если ELSE отсутствует } Check(tLex.lexEND, "END"); Gen.Fixup(LastGOTO); //Направить сюда все GOTO }
// Множитель {ОперУмн Множитель} static tType Term() { tLex Op; tType T = Factor(); if (Scan.Lex == tLex.lexMult || Scan.Lex == tLex.lexDIV || Scan.Lex == tLex.lexMOD) { if (T != tType.Int) { Error.Message( "Несоответствие операции типу операнда" ); } do { Op = Scan.Lex; Scan.NextLex(); if ((T = Factor()) != tType.Int) { Error.Expected("выражение целого типа"); } switch (Op) { case tLex.lexMult: Gen.Cmd(OVM.cmMult); break; case tLex.lexDIV: Gen.Cmd(OVM.cmDiv); break; case tLex.lexMOD: Gen.Cmd(OVM.cmMod); break; } } while(Scan.Lex == tLex.lexMult || Scan.Lex == tLex.lexDIV || Scan.Lex == tLex.lexMOD); } return(T); }
static void StProc(int P) { switch (P) { case spDEC: Variable(); Gen.Cmd(OVM.cmDup); Gen.Cmd(OVM.cmLoad); if (Scan.Lex == tLex.lexComma) { Scan.NextLex(); IntExpression(); } else { Gen.Cmd(1); } Gen.Cmd(OVM.cmSub); Gen.Cmd(OVM.cmSave); return; case spINC: Variable(); Gen.Cmd(OVM.cmDup); Gen.Cmd(OVM.cmLoad); if (Scan.Lex == tLex.lexComma) { Scan.NextLex(); IntExpression(); } else { Gen.Cmd(1); } Gen.Cmd(OVM.cmAdd); Gen.Cmd(OVM.cmSave); return; case spInOpen: // Пусто ; return; case spInInt: Variable(); Gen.Cmd(OVM.cmIn); Gen.Cmd(OVM.cmSave); return; case spOutInt: IntExpression(); Check(tLex.lexComma, "\",\""); IntExpression(); Gen.Cmd(OVM.cmOut); return; case spOutLn: Gen.Cmd(OVM.cmOutLn); return; case spHALT: Gen.Const(ConstExpr()); Gen.Cmd(OVM.cmStop); return; } }