private bool Analyze() { PrintStackAndInput(); while (true) { PrintStackAndInput(); char stack_symb = PopFromStack(); if (stack_symb == emptyProduction) { continue; } Lexema lexema = input.peekLexema(); char seqence_symb = lexema.symbol; if (stack_symb == seqence_symb) { if (stack_symb == stopSymbol) { Console.WriteLine("String is perfect."); return(true); } else { input.get(); //отстранява се следващия символ от потока } } else { //предполага се, че символа, взет от стека, е нетерминален //търсене на нетерм. символ в table_entry Hashtable table_entry = (Hashtable)productionsTable[stack_symb]; if (table_entry != null) { //търсене на продукция за замяна на нетерм. символ String production = (String)table_entry[seqence_symb]; if (production != null) { //към стека се добавя нужната продукция PushIntoStack(production); PrintProduction(stack_symb, production); } else { //не съществува продукция, за да получим stack_symb => seqence_symb SyntaxError(String.Format("Не съществува продукция {0} => {1}", stack_symb, seqence_symb), lexema.row); return(false); } } else { //няма такъв нетерминален символ или това е терминален символ, //различен от този във входната редица SyntaxError(String.Format("Символът от стека '{0}' е терминален " + "и не съвпада със символа от входната редица: '(1)' " + "или е нетерминален и не образува продукции", stack_symb, seqence_symb), lexema.row); return(false); } } } }
public Lexema getLexema() { Lexema lexema = peekLexema(); position++; return(lexema); }
private bool changeSymbol(LexemaSequence input, Lexema lexema, char search_symbol, char replace_symbol) { if (lexema.symbol == search_symbol) { if (input.GetPosition() > 1) { if (input.getLexema(input.GetPosition() - 2).symbol == Expression.IDENTIFIER) { lexema.symbol = replace_symbol; return(true); } } if (input.GetPosition() < input.size()) { if (input.peekLexema().symbol == Expression.IDENTIFIER) { //това е префиксна операция, не се прави заместване return(true); } else { Console.WriteLine(search_symbol + " can be applyed only to identifier."); return(false); } } Console.WriteLine("Error 1002."); return(false); } else { return(true); } }
private void checkUnaryMinus(LexemaSequence input, Lexema lexema) { if (lexema.symbol == Expression.MINUS) { bool must_change = false; if (input.GetPosition() > 1) { char symbol = input.getLexema(input.GetPosition() - 2).symbol; if ((symbol == Expression.ASSIGNMENT) || (symbol == Expression.OPEN_BRACE) || (symbol == Expression.PLUS) || (symbol == Expression.MULTUPLICATION) || (symbol == Expression.BITWISE_OR) || (symbol == Expression.DIVISION) || (symbol == Expression.MODUL) || (symbol == Expression.BITWISE_AND) || (symbol == Expression.BITWISE_INVERSION) || (symbol == Expression.BOOLEAN_INVERSION)) { must_change = true; } } else { must_change = true; } if (must_change) { lexema.symbol = Expression.UNARY_MINUS; } } }
//открива и заменя постфиксни ++ и -- с други символи private bool incAndDecSymbolDeal(LexemaSequence input, Lexema lexema) { bool ret = true; ret = changeSymbol(input, lexema, Expression.PREFIX_INCREMENT, Expression.POSTFIX_INCREMENT); if (ret == true) { ret = changeSymbol(input, lexema, Expression.PREFIX_DECREMENT, Expression.POSTFIX_DECREMENT); } return(ret); }
public Lexema pop() { if (lexemas.Count > 0) { Lexema ret = (Lexema)lexemas[lexemas.Count - 1]; lexemas.RemoveAt(lexemas.Count - 1); return(ret); } else { return(null); } }
private bool parseStatements() { //входната поредица ще се обработва израз по израз (разделени са с ';') try { asmCode = asmHeader; input.rewind(); int input_size = input.size(); Statement stmt = new Statement(); for (int i = 0; i < input_size; i++) { Lexema lexema = input.getLexema(); if (lexema.symbol != Expression.SEMICOLON) { incAndDecSymbolDeal(input, lexema); checkUnaryMinus(input, lexema); if (stmt.convertIntoRPN(lexema) == false) { return(false); } } else { //прехвърля всичко от стека на изходната редица ArrayList postfix_expressions = stmt.completeRPN(); //<Lexema> //израза се преобразува в асемблерен код asmCode += stmt.generateAsembler(); //добавя се израза, съдържащ само постфиксни оператори if (postfix_expressions.Count != 0) { Statement postfix_stmt = new Statement(postfix_expressions); //израза се преобразува в асемблерен код asmCode += postfix_stmt.generateAsembler(); } stmt = new Statement(); } } asmCode += returnDOS; asmCode += writeIncludedProcs(); asmCode += asmFooter; Console.WriteLine("\nASSEMBLER CODE:\n" + asmCode); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); return(false); } return(true); }
//връща последователността от лексеми от текущата позиция до края public override String ToString() { String symbol_sequence = ""; int pos = 0; IEnumerator iter = sequence.GetEnumerator(); while (iter.MoveNext()) { Lexema lexema = (Lexema)iter.Current; if (pos >= position) { symbol_sequence += lexema.symbol; } pos++; } return(symbol_sequence); }
private String getAddressOrValue(Lexema lexema) { if (lexema.symbol == intermediateLexemaSymbol) { //това е on-the-fly стойност return(String.Format(savePlace, lexema.address)); } else if (lexema.symbol == Expression.IDENTIFIER) { return(String.Format("dword ptr [ebp+{0}]", lexema.address)); } else if (lexema.symbol == Expression.NUMBER) { return(lexema.value.ToString()); } else { throw new Exception("Error 1005: no match found for symbol: " + lexema.symbol); } }
private bool assignmentSignDeal() { //претърсват се символите от входната редица и ако има различни //от идентификатор или знак '=' значи има семантична грешка IEnumerator iter = stmt.GetEnumerator(); //<Lexema> while (iter.MoveNext()) { Lexema lexema = (Lexema)iter.Current; if ((lexema.symbol != Expression.ASSIGNMENT) && (lexema.symbol != Expression.IDENTIFIER) && (lexema.symbol != Expression.OPEN_BRACE) && (lexema.symbol != Expression.CLOSE_BRACE)) { Console.WriteLine("Left of assigment sign '=' can be only" + " identifier."); return(false); } } return(true); }
//генерира асмеблерен код за целия израз (statement) public String generateAsembler() { Asembler asm = new Asembler(); String asmCode = ""; IEnumerator iter = stmt.GetEnumerator(); //<Lexema> while (iter.MoveNext()) { Lexema lexema = (Lexema)iter.Current; Expression expression_sign = (Expression)expressions[lexema.symbol]; //ако поредния символ е операнд го пишем в стека if (expression_sign == null) { stack.push(lexema); } //това е оператор, може да е унарен или да работи с две стойности Asembler.Result result = asm.processSingleOperation(lexema); if (result != null) { asmCode += result.code; if (result.savedIn == Asembler.Result.IN_SAVE_PLACE) { //индикация, че на тази позиция има нещо, //чиято стойност е вече сметната //и трябва да се вземе например от програмния стек stack.push(new Lexema(intermediateLexemaSymbol, 0, getLastAddress(), Lexema.NO_VALUE)); } } } //TODO: провери дали стека е празен, защото ако не е празен и //израза не е бил само с постфиксни оператори значи има грешка stack.clear(); Console.WriteLine("CODE FOR STATEMENT: " + this.ToString() + "\n" + asmCode + "\n"); return(asmCode); }
public void push(Lexema lexema) { lexemas.Add(lexema); }
//генерира асемблерен код за единичен оператор public Result processSingleOperation(Lexema lexema) { switch (lexema.symbol) { case Expression.PLUS: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doPlus(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.ASSIGNMENT: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.peek(); return(new Result(doAssignment(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_MEMORY)); } case Expression.MINUS: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doMinus(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.PREFIX_INCREMENT: case Expression.POSTFIX_INCREMENT: { Lexema only_side_lexema = stack.peek(); return(new Result(doIncrement(getAddressOrValue(only_side_lexema)), Result.IN_MEMORY)); } case Expression.PREFIX_DECREMENT: case Expression.POSTFIX_DECREMENT: { Lexema only_side_lexema = stack.peek(); return(new Result(doDecrement(getAddressOrValue(only_side_lexema)), Result.IN_MEMORY)); } case Expression.BITWISE_INVERSION: { Lexema only_side_lexema = stack.pop(); return(new Result(doBitwiseInversion(getAddressOrValue(only_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.BITWISE_AND: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doBitwiseAnd(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.BITWISE_OR: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doBitwiseOr(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.BOOLEAN_INVERSION: { Lexema only_side_lexema = stack.pop(); return(new Result(doBooleanInversion(getAddressOrValue(only_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.UNARY_MINUS: { Lexema only_side_lexema = stack.pop(); return(new Result(doUnaryMinus(getAddressOrValue(only_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.MULTUPLICATION: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doMultiplication(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.DIVISION: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doDivision(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.MODUL: { Lexema right_side_lexema = stack.pop(); Lexema left_side_lexema = stack.pop(); return(new Result(doModul(getAddressOrValue(right_side_lexema), getAddressOrValue(left_side_lexema)), Result.IN_SAVE_PLACE)); } case Expression.PRINTF: { Lexema only_side_lexema = stack.pop(); return(new Result(doPrintf(getAddressOrValue(only_side_lexema)), Result.IN_MEMORY)); } case Expression.SCANF: { stack.pop(); return(new Result(doScanf(), Result.IN_SAVE_PLACE)); } } return(null); }
public bool convertIntoRPN(Lexema lexema) { Expression expression_sign = (Expression)expressions[lexema.symbol]; //ако поредния символ е операнд или константа го пишем направо на изходната редица if (expression_sign == null) { stmt.Add(lexema); } else { //това е оператор if (expression_sign.symbol == Expression.CLOSE_BRACE) { //затварящата скоба предизвиква изхвърляне на символи от стека //докато се срещне отваряща скоба. Двете се унищожават. //взима се лексемата от върха на стека Lexema TOS_lexema = stack.peek(); //проверка за празен стек if (TOS_lexema != null) { //стекът не е празен Expression TOS_expression_sign = (Expression)expressions[TOS_lexema.symbol]; while (TOS_expression_sign.symbol != Expression.OPEN_BRACE) { //предизвиква се изхвърляне на символи от стека към изходната редица TOS_lexema = stack.pop(); stmt.Add(TOS_lexema); //поглежда се какъв е следващия символ от стека TOS_lexema = stack.peek(); if (TOS_lexema != null) { TOS_expression_sign = (Expression)expressions[TOS_lexema.symbol]; } else { //стекът вече е празен Console.WriteLine("ERROR 1000: " + "Can not find open brace while executing RPN"); return(false); } } //премахва се отварящата скоба от стека stack.pop(); } else { Console.WriteLine("ERROR 1001: " + "Can not find open brace while executing RPN"); return(false); } } else { //постфиксните ++ и -- се обработват по различен начин начин if ((expression_sign.symbol == Expression.POSTFIX_INCREMENT) || (expression_sign.symbol == Expression.POSTFIX_DECREMENT)) { //добавя се предишния идентификатор postfix.Add(stmt[stmt.Count - 1]); //добавя се и самата лексема postfix.Add(lexema); } else { //обработват се останалите лексеми //взима се лексемата от върха на стека Lexema TOS_lexema = stack.peek(); //проверка за празен стек if (TOS_lexema != null) { //стекът не е празен Expression TOS_expression_sign = (Expression)expressions[TOS_lexema.symbol]; while (expression_sign.outOfStackPriority <= TOS_expression_sign.inStackPriority) { //текъщия символ е с по-нисък или равен приоритет и ще //предизвика изхвърляне на символи от стека към изходната редица TOS_lexema = stack.pop(); stmt.Add(TOS_lexema); //поглежда се какъв е следващия символ от стека TOS_lexema = stack.peek(); if (TOS_lexema != null) { TOS_expression_sign = (Expression)expressions[TOS_lexema.symbol]; } else { break; //стекът вече е празен } } } stack.push(lexema); } } if (expression_sign.symbol == Expression.ASSIGNMENT) { if (assignmentSignDeal() == false) { return(false); } } } return(true); }