# HG changeset patch # User Fahad Ausaf # Date 1415795066 0 # Node ID 7545b1bc15147f316d5cf0c860b9e8c6f1ce45e3 # Parent a751aa1ee4f770b6864f805b05b863e4097f44a4 msc project diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/AST.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/AST.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Text; + + +public abstract class Statement +{ +} + +public class DeclareVariable : Statement +{ + public string Identifier; + public Expression Expression; +} + +public class DeclareFunction : Statement +{ + public string FunctionName; + public DeclareVariable Parameter1; + public DeclareVariable Parameter2; + public DeclareVariable Parameter3; + public String ReturnType; + public Statement Body; +} + +public class CallFunction : Statement +{ + public string FunctionName; + public Expression Parameter1; + public Expression Parameter2; + public Expression Parameter3; + public Identifier ReturnVariable; +} + +public class Write : Statement +{ + public Expression Expression; +} + +public class Assignment : Statement +{ + public string Identifier; + public Expression Expression; +} + +public class For : Statement +{ + public string Identifier; + public Expression From; + public Expression To; + public Statement Body; +} + +public class IfThenElse : Statement +{ + public Expression If; + public Statement Then; + public Statement Else; +} + +public class IfThen : Statement +{ + public Expression LeftExpression; + public RelationalOperands Operand; + public Expression RightExpression; + public Statement ThenBody; + public Statement ElseBody; +} + +public class While : Statement +{ + public Expression LeftExpression; + public RelationalOperands Operand; + public Expression RightExpression; + public Statement Body; +} + +public class ReadInput : Statement +{ + public string Identifier; +} + +public class StatementSequence : Statement +{ + public Statement Left; + public Statement Right; +} + +public abstract class Expression +{ +} + +public class AlphaNumericValue : Expression +{ + public string Value; +} + +public class NumericValue : Expression +{ + public int Value; +} + +public class Identifier : Expression +{ + public string IdentifierName; +} + +public class ArithmaticExpression : Expression +{ + public Expression Left; + public Expression Right; + public ArithmaticOperands Operand; +} + +public enum ArithmaticOperands +{ + Add, + Subtract, + Multiply, + Division +} + +public class LogicalExpression : Expression +{ + public Expression Left; + public Expression Right; + public LogicalOperands Operand; +} + +public enum LogicalOperands +{ + Or, + And, + Xor, + Not +} + +public class RelationalExpression : Expression +{ + public Expression Left; + public Expression Right; + public RelationalOperands Operand; +} + +public class CompareVariable : Statement +{ + public string Identifier; + public Expression Expression; + public RelationalOperands Operand; +} + +public enum RelationalOperands +{ + EqualTo, + NotEqualTo, + LessThan, + LessThanOrEqualTo, + GreaterThan, + GreaterThanOrEqualTo +} diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Factorial2.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Factorial2.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,13 @@ +var fact = 7; + +fact = fact + 1; + +var c = 0; +var result = 1; + +for c = 1 to fact do + result = result * c; +end; + +print "The factorial is:"; +print result; \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Fibonaci.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Fibonaci.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,19 @@ +var fib = 0; +print "Enter a number to calculate fibonaci"; +read fib; +fib = fib + 1; + +var a = 0; +var b = 1; + +var i = 0; +for i = 0 to fib do + var temp = a; + a = b; + b = temp + b; +end; + +print "The result is:"; +print b; + +read b; \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Fibonaci3.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Fibonaci3.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,16 @@ +var fib = 7; + +fib = fib + 1; + +var a = 0; +var b = 1; + +var i = 0; +for i = 0 to fib do + var temp = a; + a = b; + b = temp + b; +end; + +print "The result is:"; +print b; \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Greetings.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Greetings.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,11 @@ +var x = 2; +var y = 3; +var z = y; +print z; + +var msg = "Hello World"; +print msg; + +var n = 0; +print "Enter any number from 0 to 9 to continue"; +read n; \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Math.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Math.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,6 @@ +var a = 5; + + +a = a + 3; +print a; + diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Nested-For.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Nested-For.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,15 @@ +var n = 0; +print "Rate King's College from 1 to 10"; +read n; + +var x = 0; +for x = 0 to n do + print "King's College is the best!"; + + var z = 0; + for z = x to n do + print z; + end; +end; + +read n; diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/Nested-For2.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/Nested-For2.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,13 @@ +print "Rate King's College from 1 to 10"; +var n = 5; + +var x = 0; +for x = 0 to n do + print "King's College is the best!"; + + var z = 0; + for z = x to n do + print z; + end; +end; + diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/While.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/While.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,11 @@ +var FirstNum = 10; +var SecondNum = 5; + +while FirstNum > SecondNum do + print FirstNum; + + FirstNum = FirstNum - 1; +endwhile; + +print "Enter any number to continue"; +read SecondNum; \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/code.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/code.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,11 @@ +void TestFunction var output = 0, var inputA = 1, var inputB = 2 +begin + var test = 0; + test = inputA + inputB; + print test; +endfunc; + +var one = 1; +var two = 2; +var three = 3; + diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/for-loop.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/for-loop.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,11 @@ +var ntimes = 0; +print "Rate King's College from 1 to 10"; +read ntimes; +var x = 0; +var y = 0; +for x = y to ntimes do + print "King's College is the best"; +end; +print "press any key to continue..."; +var continue = 0; +read continue; diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/if-then.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/if-then.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,23 @@ +var FirstNum = 0; +var SecondNum = 0; + +print "enter first number"; +read FirstNum; + +print "enter second number"; +read SecondNum; + +if FirstNum > SecondNum then + if FirstNum > 9 then + print "First Number is greater then 9"; + else + print "First Number is less then 9"; + endif; + print "first number is GREATER than second number"; +else + print "first number is LESS than second number"; +endif; + +var z = 0; +print "enter any number to continue"; +read z; \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Code/if-then2.kcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Code/if-then2.kcl Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,16 @@ +var FirstNum = 25; +var SecondNum = 15; + + + +if FirstNum > SecondNum then + if FirstNum > 9 then + print "First Number is greater then 9"; + else + print "First Number is less then 9"; + endif; + print "first number is GREATER than second number"; +else + print "first number is LESS than second number"; +endif; + diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/CodeGenerator.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/CodeGenerator.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,874 @@ +using System; +using System.Collections.Generic; +using System.Text; +// Added +using System.Reflection; +using System.Reflection.Emit; +using System.IO; + +public sealed class CodeGenerator +{ + + Dictionary tblIdentifier; + Dictionary tblArguments; + TypeBuilder _typeBuilder = null; + System.Reflection.Emit.ILGenerator _ILGenerator = null; + MemberInfo WriteLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); + + #region Statement + public CodeGenerator(Statement statement, string fileName) + { + string strFileName = Path.GetFileNameWithoutExtension(fileName); + + #region Define Assembly + //AssemblyName _AssemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(fileName)); + AssemblyName _AssemblyName = new AssemblyName(strFileName); + AppDomain currentDomain = AppDomain.CurrentDomain; + AssemblyBuilder _AssemblyBuilder = currentDomain.DefineDynamicAssembly(_AssemblyName, AssemblyBuilderAccess.Save); + #endregion + + #region Define Module + ModuleBuilder _ModuleBuilder = _AssemblyBuilder.DefineDynamicModule(fileName); + #endregion + + _typeBuilder = _ModuleBuilder.DefineType("CodeGenerator"); + MethodBuilder _MethodBuilder = _typeBuilder.DefineMethod + ("Main", + MethodAttributes.Static, + typeof(void), + System.Type.EmptyTypes); + + _ILGenerator = _MethodBuilder.GetILGenerator(); + tblIdentifier = new Dictionary(); + tblArguments = new Dictionary(); + + // CIL generation + GenerateStatement(statement); + + _ILGenerator.Emit(OpCodes.Ret); + _typeBuilder.CreateType(); + _ModuleBuilder.CreateGlobalFunctions(); + _AssemblyBuilder.SetEntryPoint(_MethodBuilder); + _AssemblyBuilder.Save(fileName); + tblIdentifier = null; + _ILGenerator = null; + } + + public void GenerateStatement(Statement _statement) + { + if (_statement is StatementSequence) + { + StatementSequence _StatementSequence = (StatementSequence)_statement; + GenerateStatement(_StatementSequence.Left); + GenerateStatement(_StatementSequence.Right); + } + + else if (_statement is DeclareVariable) + { + // declare a variable in symbol table + DeclareVariable declare = (DeclareVariable)_statement; + tblIdentifier[declare.Identifier] = + _ILGenerator.DeclareLocal(GetExpressionType(declare.Expression)); + + // set the initial value + Assignment assign = new Assignment(); + assign.Identifier = declare.Identifier; + assign.Expression = declare.Expression; + GenerateStatement(assign); + } + + else if (_statement is Assignment) + { + Assignment assign = (Assignment)_statement; + GenerateExpression(assign.Expression, + GetExpressionType(assign.Expression)); + if (GetExpressionType(assign.Expression) == typeof(ArithmaticExpression)) + { + SaveIdentifier(assign.Identifier, typeof(Int32)); + } + else + { + SaveIdentifier(assign.Identifier, + GetExpressionType(assign.Expression)); + } + + } + + else if (_statement is DeclareFunction) + { + GenerateStatementMethod(_statement); + } + + else if (_statement is Write) + { + // for print keyword, call .net method for printscreen + GenerateExpression(((Write)_statement).Expression, + typeof(string)); + _ILGenerator.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("WriteLine", + new System.Type[] { typeof(string) })); + } + + else if (_statement is ReadInput) + { + // call the readline method and parse input method + _ILGenerator.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("ReadLine", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { }, null)); + _ILGenerator.Emit(OpCodes.Call, + typeof(int).GetMethod("Parse", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { typeof(string) }, null)); + // store the input value in local builder + SaveIdentifier(((ReadInput)_statement).Identifier, typeof(int)); + } + else if (_statement is IfThenElse) + { + + //IfThenElse ifThenElse = (IfThenElse)stmt; + //RelationalExpression relExpr = (RelationalExpression)ifThenElse.If; + //// if, left side only + //il.Emit(OpCodes.Stloc, symbolTable[relExpr.Left.ToString()]); + //Label lblIf = il.DefineLabel(); + //il.Emit(OpCodes.Br, lblIf); + //// then + //Label lblThen = il.DefineLabel(); + //il.MarkLabel(lblThen); + + } + + else if (_statement is While) + { + While _while = (While)_statement; + Label lblTest = _ILGenerator.DefineLabel(); + Label lblEnd = _ILGenerator.DefineLabel(); + + if (_while.Operand == RelationalOperands.GreaterThan) + { + _ILGenerator.MarkLabel(lblTest); + GenerateExpression(_while.LeftExpression, typeof(int)); + GenerateExpression(_while.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Cgt); + _ILGenerator.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatement(_while.Body); + _ILGenerator.Emit(OpCodes.Br, lblTest); + + _ILGenerator.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.EqualTo) + { + _ILGenerator.MarkLabel(lblTest); + GenerateExpression(_while.LeftExpression, typeof(int)); + GenerateExpression(_while.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Ceq); + _ILGenerator.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatement(_while.Body); + _ILGenerator.Emit(OpCodes.Br, lblTest); + + _ILGenerator.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.LessThan) + { + _ILGenerator.MarkLabel(lblTest); + GenerateExpression(_while.LeftExpression, typeof(int)); + GenerateExpression(_while.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Clt); + _ILGenerator.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatement(_while.Body); + _ILGenerator.Emit(OpCodes.Br, lblTest); + + _ILGenerator.MarkLabel(lblEnd); + } + } + else if (_statement is IfThen) + { + #region + //////Label body = il.DefineLabel(); + + //////il.Emit(OpCodes.Ldc_I4, 1000); + + + + /* + // var x = 0; + // if x < 5 then + // print "less than 5"; + // endif; + + IfThen ifThen = (IfThen)stmt; + // jump to test + + + // **test** if x LessThan 5? (do the test) + il.MarkLabel(test); + GenExpr(ifThen.LeftExpression, typeof(int)); + + */ + + //Label greaterThan = il.DefineLabel(); + + //IfThen ifThen = (IfThen)stmt; + //GenExpr(ifThen.LeftExpression, typeof(int)); + //GenExpr(ifThen.RightExpression, typeof(int)); + //if (ifThen.Operand == RelationalOperands.GreaterThan) + //{ + // + //} + #endregion + + IfThen ifThen = (IfThen)_statement; + Label lblElse = _ILGenerator.DefineLabel(); + Label lblEnd = _ILGenerator.DefineLabel(); + + #region GreaterThan + if (ifThen.Operand == RelationalOperands.GreaterThan) + { + GenerateExpression(ifThen.LeftExpression, typeof(int)); + GenerateExpression(ifThen.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Cgt); + _ILGenerator.Emit(OpCodes.Brfalse, lblElse); + GenerateStatement(ifThen.ThenBody); + _ILGenerator.Emit(OpCodes.Br, lblEnd); + + _ILGenerator.MarkLabel(lblElse); + GenerateStatement(ifThen.ElseBody); + + _ILGenerator.MarkLabel(lblEnd); + } + #endregion + #region EqualTo + else if (ifThen.Operand == RelationalOperands.EqualTo) + { + GenerateExpression(ifThen.LeftExpression, typeof(int)); + GenerateExpression(ifThen.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Ceq); + _ILGenerator.Emit(OpCodes.Brfalse, lblElse); + GenerateStatement(ifThen.ThenBody); + _ILGenerator.Emit(OpCodes.Br, lblEnd); + + _ILGenerator.MarkLabel(lblElse); + GenerateStatement(ifThen.ElseBody); + + _ILGenerator.MarkLabel(lblEnd); + } + #endregion + #region LessThan + else if (ifThen.Operand == RelationalOperands.LessThan) + { + GenerateExpression(ifThen.LeftExpression, typeof(int)); + GenerateExpression(ifThen.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Clt); + _ILGenerator.Emit(OpCodes.Brfalse, lblElse); + GenerateStatement(ifThen.ThenBody); + _ILGenerator.Emit(OpCodes.Br, lblEnd); + + _ILGenerator.MarkLabel(lblElse); + GenerateStatement(ifThen.ElseBody); + + _ILGenerator.MarkLabel(lblEnd); + } + #endregion + + #region + /* + Label gtTrue = il.DefineLabel(); + Label gtFalse = il.DefineLabel(); + + + */ + #endregion + + } + else if (_statement is For) + { + // example: + // for x = 0 to 100 do + // print "hello"; + // end; + + // x = 0 + For forLoop = (For)_statement; + Assignment assign = new Assignment(); + assign.Identifier = forLoop.Identifier; + assign.Expression = forLoop.From; + GenerateStatement(assign); + // jump to the test + Label test = _ILGenerator.DefineLabel(); + _ILGenerator.Emit(OpCodes.Br, test); + + // body statement + Label body = _ILGenerator.DefineLabel(); + _ILGenerator.MarkLabel(body); + GenerateStatement(forLoop.Body); + + // increase x + _ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + _ILGenerator.Emit(OpCodes.Ldc_I4, 1); + _ILGenerator.Emit(OpCodes.Add); + SaveIdentifier(forLoop.Identifier, typeof(int)); + + // check if x is equal to 100 + _ILGenerator.MarkLabel(test); + _ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + GenerateExpression(forLoop.To, typeof(int)); + _ILGenerator.Emit(OpCodes.Blt, body); + } + + else + { + ExceptionHandler("unable to generate " + _statement.GetType().Name); + } + } + + public void ExceptionHandler(string strException) + { + throw new Exception(strException); + } + + public void SaveIdentifier(string IdentifierName, System.Type IdentifierType) + { + if (tblIdentifier.ContainsKey(IdentifierName)) + { + LocalBuilder locb = tblIdentifier[IdentifierName]; + + if (locb.LocalType == IdentifierType) + { + _ILGenerator.Emit(OpCodes.Stloc, tblIdentifier[IdentifierName]); + } + else + { + ExceptionHandler("'" + IdentifierName + "' is of type " + locb.LocalType.Name + " but saving in different type " + IdentifierType.Name); + } + } + else + { + ExceptionHandler("variable not declared '" + IdentifierName + "'"); + } + } + + public void GenerateExpression(Expression _expression, System.Type expressionType) + { + System.Type typeOfExpression; + + if (_expression is AlphaNumericValue) + { + typeOfExpression = typeof(string); + _ILGenerator.Emit(OpCodes.Ldstr, ((AlphaNumericValue)_expression).Value); + } + else if (_expression is NumericValue) + { + typeOfExpression = typeof(int); + _ILGenerator.Emit(OpCodes.Ldc_I4, ((NumericValue)_expression).Value); + } + + else if (_expression is ArithmaticExpression) + { + typeOfExpression = GetExpressionType(_expression); + + ArithmaticExpression arithmaticExpression = (ArithmaticExpression)_expression; + GenerateExpression(arithmaticExpression.Left, GetExpressionType(arithmaticExpression.Left)); + GenerateExpression(arithmaticExpression.Right, GetExpressionType(arithmaticExpression.Right)); + if (arithmaticExpression.Operand == ArithmaticOperands.Add) + { + _ILGenerator.Emit(OpCodes.Add); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Subtract) + { + _ILGenerator.Emit(OpCodes.Sub); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Multiply) + { + _ILGenerator.Emit(OpCodes.Mul); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Division) + { + _ILGenerator.Emit(OpCodes.Div); + } + } + + + else if (_expression is Identifier) + { + string identifier = ((Identifier)_expression).IdentifierName; + typeOfExpression = GetExpressionType(_expression); + + if (!tblIdentifier.ContainsKey(identifier)) + { + ExceptionHandler("undeclared variable '" + identifier + "'"); + } + + _ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[identifier]); + } + + else + { + ExceptionHandler("can't generate " + _expression.GetType().Name); + typeOfExpression = null; + } + + if (typeOfExpression != expressionType) + { + if (typeOfExpression == typeof(int) && + expressionType == typeof(string)) + { + _ILGenerator.Emit(OpCodes.Box, typeof(int)); + _ILGenerator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); + } + else + { + ExceptionHandler("can't convert " + typeOfExpression.Name + " to " + expressionType.Name); + } + } + + } + + public System.Type GetExpressionType(Expression _expression) + { + if (_expression is AlphaNumericValue) + { + return typeof(string); + } + else if (_expression is NumericValue) + { + return typeof(int); + } + else if (_expression is Identifier) + { + Identifier var = (Identifier)_expression; + if (tblIdentifier.ContainsKey(var.IdentifierName)) + { + LocalBuilder locb = tblIdentifier[var.IdentifierName]; + return locb.LocalType; + } + else + { + ExceptionHandler("variable not declared '" + var.IdentifierName + "'"); + return null; + } + } + else if (_expression is ArithmaticExpression) + { + return typeof(ArithmaticExpression); + } + else + { + ExceptionHandler("type cannot be generated for " + _expression.GetType().Name); + return null; + } + } + + #endregion + + #region Method + + System.Reflection.Emit.ILGenerator _ILMethod = null; + public void GenerateStatementMethod(Statement _statement) + { + #region Statement + if (_statement is StatementSequence) + { + StatementSequence _StatementSequence = (StatementSequence)_statement; + GenerateStatementMethod(_StatementSequence.Left); + GenerateStatementMethod(_StatementSequence.Right); + } + #endregion + + #region Declare Variable + else if (_statement is DeclareVariable) + { + // declare a variable in symbol table + DeclareVariable declare = (DeclareVariable)_statement; + tblIdentifier[declare.Identifier] = + _ILMethod.DeclareLocal(GetExpressionTypeMethod(declare.Expression)); + + // set the initial value + Assignment assign = new Assignment(); + assign.Identifier = declare.Identifier; + assign.Expression = declare.Expression; + GenerateStatementMethod(assign); + } + #endregion + + #region Assignment + else if (_statement is Assignment) + { + Assignment assign = (Assignment)_statement; + GenerateExpressionMethod(assign.Expression, GetExpressionTypeMethod(assign.Expression)); + if (GetExpressionTypeMethod(assign.Expression) == typeof(ArithmaticExpression)) + { + SaveIdentifierMethod(assign.Identifier, typeof(Int32)); + } + else + { + SaveIdentifierMethod(assign.Identifier, + GetExpressionTypeMethod(assign.Expression)); + } + + } + #endregion + + else if (_statement is DeclareFunction) + { + DeclareFunction _DeclareFunction = (DeclareFunction)_statement; + + string strFunctionName = _DeclareFunction.FunctionName; + + Type ParameterType1 = GetExpressionTypeMethod(_DeclareFunction.Parameter1.Expression); + Type ParameterType2 = GetExpressionTypeMethod(_DeclareFunction.Parameter2.Expression); + Type ParameterType3 = GetExpressionTypeMethod(_DeclareFunction.Parameter3.Expression); + Type[] InputParameters = { ParameterType1, ParameterType2, ParameterType3 }; + + Type ReturnType = typeof(void); + if(_DeclareFunction.ReturnType == "void") + ReturnType = typeof(void); + else if (_DeclareFunction.ReturnType == "string") + ReturnType = typeof(string); + else if (_DeclareFunction.ReturnType == "numeric") + ReturnType = typeof(int); + + + + //FieldBuilder Parameter1 = _typeBuilder.DefineField(_DeclareFunction.Parameter1.Identifier, ParameterType1, FieldAttributes.Private); + //FieldBuilder Parameter2 = _typeBuilder.DefineField(_DeclareFunction.Parameter2.Identifier, ParameterType2, FieldAttributes.Private); + //FieldBuilder Parameter3 = _typeBuilder.DefineField(_DeclareFunction.Parameter3.Identifier, ParameterType3, FieldAttributes.Private); + + MethodBuilder NewMethod = + _typeBuilder.DefineMethod + (strFunctionName, + MethodAttributes.Static, + ReturnType, + InputParameters); + + //ParameterBuilder poolRefBuilder = NewMethod.DefineParameter(1, ParameterAttributes.In, _DeclareFunction.Parameter1.Identifier); + + _ILMethod = NewMethod.GetILGenerator(); + + + //tblArguments[_DeclareFunction.Parameter0.Identifier] = _ILMethod. + + tblArguments[_DeclareFunction.Parameter1.Identifier] = _ILMethod.DeclareLocal(ParameterType1); + GenerateExpressionMethod(_DeclareFunction.Parameter1.Expression, ParameterType1); + //_ILMethod.Emit(OpCodes.Starg, 0); + + tblArguments[_DeclareFunction.Parameter1.Identifier] = _ILMethod.DeclareLocal(ParameterType2); + GenerateExpressionMethod(_DeclareFunction.Parameter1.Expression, ParameterType2); + //_ILMethod.Emit(OpCodes.Starg, 1); + + tblArguments[_DeclareFunction.Parameter2.Identifier] = _ILMethod.DeclareLocal(ParameterType3); + GenerateExpressionMethod(_DeclareFunction.Parameter2.Expression, ParameterType3); + //_ILMethod.Emit(OpCodes.Starg, 2); + + //GenerateStatementMethod(_DeclareFunction.Body); + //_ILMethod.Emit(OpCodes.Ret); + } + + #region write-read + else if (_statement is Write) + { + // for print keyword, call .net method for printscreen + GenerateExpressionMethod(((Write)_statement).Expression, + typeof(string)); + _ILMethod.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("WriteLine", + new System.Type[] { typeof(string) })); + } + + else if (_statement is ReadInput) + { + // call the readline method and parse input method + _ILMethod.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("ReadLine", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { }, null)); + _ILMethod.Emit(OpCodes.Call, + typeof(int).GetMethod("Parse", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { typeof(string) }, null)); + // store the input value in local builder + SaveIdentifierMethod(((ReadInput)_statement).Identifier, typeof(int)); + } + #endregion + + #region While + else if (_statement is While) + { + While _while = (While)_statement; + Label lblTest = _ILMethod.DefineLabel(); + Label lblEnd = _ILMethod.DefineLabel(); + + if (_while.Operand == RelationalOperands.GreaterThan) + { + _ILMethod.MarkLabel(lblTest); + GenerateExpressionMethod(_while.LeftExpression, typeof(int)); + GenerateExpressionMethod(_while.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Cgt); + _ILMethod.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatementMethod(_while.Body); + _ILMethod.Emit(OpCodes.Br, lblTest); + + _ILMethod.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.EqualTo) + { + _ILMethod.MarkLabel(lblTest); + GenerateExpressionMethod(_while.LeftExpression, typeof(int)); + GenerateExpressionMethod(_while.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Ceq); + _ILMethod.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatementMethod(_while.Body); + _ILMethod.Emit(OpCodes.Br, lblTest); + + _ILMethod.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.LessThan) + { + _ILMethod.MarkLabel(lblTest); + GenerateExpressionMethod(_while.LeftExpression, typeof(int)); + GenerateExpressionMethod(_while.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Clt); + _ILMethod.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatementMethod(_while.Body); + _ILMethod.Emit(OpCodes.Br, lblTest); + + _ILMethod.MarkLabel(lblEnd); + } + } + #endregion + + #region If-Then + else if (_statement is IfThen) + { + IfThen ifThen = (IfThen)_statement; + Label lblElse = _ILMethod.DefineLabel(); + Label lblEnd = _ILMethod.DefineLabel(); + + #region GreaterThan + if (ifThen.Operand == RelationalOperands.GreaterThan) + { + GenerateExpressionMethod(ifThen.LeftExpression, typeof(int)); + GenerateExpressionMethod(ifThen.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Cgt); + _ILMethod.Emit(OpCodes.Brfalse, lblElse); + GenerateStatementMethod(ifThen.ThenBody); + _ILMethod.Emit(OpCodes.Br, lblEnd); + + _ILMethod.MarkLabel(lblElse); + GenerateStatementMethod(ifThen.ElseBody); + + _ILMethod.MarkLabel(lblEnd); + } + #endregion + #region EqualTo + else if (ifThen.Operand == RelationalOperands.EqualTo) + { + GenerateExpressionMethod(ifThen.LeftExpression, typeof(int)); + GenerateExpressionMethod(ifThen.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Ceq); + _ILMethod.Emit(OpCodes.Brfalse, lblElse); + GenerateStatementMethod(ifThen.ThenBody); + _ILMethod.Emit(OpCodes.Br, lblEnd); + + _ILMethod.MarkLabel(lblElse); + GenerateStatementMethod(ifThen.ElseBody); + + _ILMethod.MarkLabel(lblEnd); + } + #endregion + #region LessThan + else if (ifThen.Operand == RelationalOperands.LessThan) + { + GenerateExpressionMethod(ifThen.LeftExpression, typeof(int)); + GenerateExpressionMethod(ifThen.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Clt); + _ILMethod.Emit(OpCodes.Brfalse, lblElse); + GenerateStatementMethod(ifThen.ThenBody); + _ILMethod.Emit(OpCodes.Br, lblEnd); + + _ILMethod.MarkLabel(lblElse); + GenerateStatementMethod(ifThen.ElseBody); + + _ILMethod.MarkLabel(lblEnd); + } + #endregion + } + #endregion + + #region for + else if (_statement is For) + { + For forLoop = (For)_statement; + Assignment assign = new Assignment(); + assign.Identifier = forLoop.Identifier; + assign.Expression = forLoop.From; + GenerateStatementMethod(assign); + + Label test = _ILMethod.DefineLabel(); + _ILMethod.Emit(OpCodes.Br, test); + + Label body = _ILMethod.DefineLabel(); + _ILMethod.MarkLabel(body); + GenerateStatementMethod(forLoop.Body); + + _ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + _ILMethod.Emit(OpCodes.Ldc_I4, 1); + _ILMethod.Emit(OpCodes.Add); + SaveIdentifierMethod(forLoop.Identifier, typeof(int)); + + _ILMethod.MarkLabel(test); + _ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + GenerateExpressionMethod(forLoop.To, typeof(int)); + _ILMethod.Emit(OpCodes.Blt, body); + } + #endregion + + else + { + ExceptionHandler("unable to generate " + _statement.GetType().Name); + } + } + + public void SaveIdentifierMethod(string IdentifierName, System.Type IdentifierType) + { + if (tblIdentifier.ContainsKey(IdentifierName)) + { + LocalBuilder locb = tblIdentifier[IdentifierName]; + + if (locb.LocalType == IdentifierType) + { + _ILMethod.Emit(OpCodes.Stloc, tblIdentifier[IdentifierName]); + } + else + { + ExceptionHandler("'" + IdentifierName + "' is of type " + locb.LocalType.Name + " but saving in different type " + IdentifierType.Name); + } + } + else + { + ExceptionHandler("variable not declared '" + IdentifierName + "'"); + } + } + + public void DeclareArgument() { } + + public void GenerateExpressionMethod(Expression _expression, System.Type expressionType) + { + System.Type typeOfExpression; + + if (_expression is AlphaNumericValue) + { + typeOfExpression = typeof(string); + _ILMethod.Emit(OpCodes.Ldstr, ((AlphaNumericValue)_expression).Value); + } + else if (_expression is NumericValue) + { + typeOfExpression = typeof(int); + _ILMethod.Emit(OpCodes.Ldc_I4, ((NumericValue)_expression).Value); + } + + else if (_expression is ArithmaticExpression) + { + typeOfExpression = GetExpressionTypeMethod(_expression); + + ArithmaticExpression arithmaticExpression = (ArithmaticExpression)_expression; + GenerateExpressionMethod(arithmaticExpression.Left, GetExpressionTypeMethod(arithmaticExpression.Left)); + GenerateExpressionMethod(arithmaticExpression.Right, GetExpressionTypeMethod(arithmaticExpression.Right)); + if (arithmaticExpression.Operand == ArithmaticOperands.Add) + { + _ILMethod.Emit(OpCodes.Add); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Subtract) + { + _ILMethod.Emit(OpCodes.Sub); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Multiply) + { + _ILMethod.Emit(OpCodes.Mul); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Division) + { + _ILMethod.Emit(OpCodes.Div); + } + } + + + else if (_expression is Identifier) + { + string identifier = ((Identifier)_expression).IdentifierName; + typeOfExpression = GetExpressionTypeMethod(_expression); + + if (!tblIdentifier.ContainsKey(identifier) && !tblArguments.ContainsKey(identifier)) + { + ExceptionHandler("undeclared variable '" + identifier + "'"); + } + + if (tblIdentifier.ContainsKey(identifier)) + _ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[identifier]); + else + _ILMethod.Emit(OpCodes.Ldloc, tblArguments[identifier]); + } + + else + { + ExceptionHandler("can't generate " + _expression.GetType().Name); + typeOfExpression = null; + } + + if (typeOfExpression != expressionType) + { + if (typeOfExpression == typeof(int) && + expressionType == typeof(string)) + { + _ILMethod.Emit(OpCodes.Box, typeof(int)); + _ILMethod.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); + } + else + { + ExceptionHandler("can't convert " + typeOfExpression.Name + " to " + expressionType.Name); + } + } + + } + + public System.Type GetExpressionTypeMethod(Expression _expression) + { + if (_expression is AlphaNumericValue) + { + return typeof(string); + } + else if (_expression is NumericValue) + { + return typeof(int); + } + else if (_expression is Identifier) + { + Identifier var = (Identifier)_expression; + if (tblIdentifier.ContainsKey(var.IdentifierName)) + { + LocalBuilder locb = tblIdentifier[var.IdentifierName]; + return locb.LocalType; + } + else if (tblArguments.ContainsKey(var.IdentifierName)) + { + LocalBuilder locb = tblArguments[var.IdentifierName]; + return locb.LocalType; + } + else + { + ExceptionHandler("variable not declared '" + var.IdentifierName + "'"); + return null; + } + } + else if (_expression is ArithmaticExpression) + { + return typeof(ArithmaticExpression); + } + else + { + ExceptionHandler("type cannot be generated for " + _expression.GetType().Name); + return null; + } + } + #endregion +} + diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/MCG-CS.csproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/MCG-CS.csproj Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,76 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {565A7BA0-5CAA-4D5D-820F-D763BF484CD5} + Exe + Properties + MCG_CS + MCG-CS + v2.0 + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/MCG-CS.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/MCG-CS.sln Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MCG-CS", "MCG-CS.csproj", "{565A7BA0-5CAA-4D5D-820F-D763BF484CD5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {565A7BA0-5CAA-4D5D-820F-D763BF484CD5}.Debug|x86.ActiveCfg = Debug|x86 + {565A7BA0-5CAA-4D5D-820F-D763BF484CD5}.Debug|x86.Build.0 = Debug|x86 + {565A7BA0-5CAA-4D5D-820F-D763BF484CD5}.Release|x86.ActiveCfg = Release|x86 + {565A7BA0-5CAA-4D5D-820F-D763BF484CD5}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/MCG-CS.suo Binary file Fahad/MCG-CS/MCG-CS.suo has changed diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Parser.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Parser.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,515 @@ +using System; +using System.Collections.Generic; +using System.Text; + +public sealed class Parser +{ + private int currentToken; + private readonly Statement parsingOutput; + private IList listTokens; + + + public Parser(IList tokens) + { + listTokens = tokens; + currentToken = 0; + parsingOutput = ParseStatement(); + + } + + public Statement GetParsedStatement + { + get { return parsingOutput; } + } + + public void ExceptionHandler(string strException) + { + throw new Exception(strException); + } + + private Statement ParseStatement() + { + Statement parsedStatement; + + if (currentToken == listTokens.Count) + { + ExceptionHandler("statement was expected before end of file"); + } + + if (listTokens[currentToken].Equals("print")) + { + currentToken++; + Write _Write = new Write(); + _Write.Expression = ParseExpression(); + parsedStatement = _Write; + } + + else if (listTokens[currentToken].Equals("var")) + { + currentToken++; + DeclareVariable _DeclareVariable = new DeclareVariable(); + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _DeclareVariable.Identifier = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("variable name was expected after 'var'"); + } + + currentToken++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.EqualTo.ToString()) + { + ExceptionHandler("= sign was expected after 'var identifier'"); + } + + currentToken++; + + _DeclareVariable.Expression = ParseExpression(); + parsedStatement = _DeclareVariable; + } + + else if (listTokens[currentToken].Equals("call")) + { + currentToken++; + CallFunction _CallFunction = new CallFunction(); + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _CallFunction.FunctionName = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("function name is expected after 'call'"); + } + currentToken++; + + _CallFunction.Parameter1 = ParseExpression(); + + //index++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.Comma.ToString()) + { + ExceptionHandler("',' sign was expected after first parameter"); + } + + currentToken++; + + _CallFunction.Parameter2 = ParseExpression(); + + //index++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.Comma.ToString()) + { + ExceptionHandler("',' sign was expected after second parameter"); + } + + currentToken++; + + _CallFunction.Parameter3 = ParseExpression(); + + //index++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.Terminator.ToString()) + { + ExceptionHandler("';' sign was expected after third parameter"); + } + + parsedStatement = _CallFunction; + } + + else if (listTokens[currentToken].Equals("string") || listTokens[currentToken].Equals("numeric") || listTokens[currentToken].Equals("void")) + { + DeclareFunction _DeclareFunction = new DeclareFunction(); + _DeclareFunction.ReturnType = listTokens[currentToken].ToString(); + currentToken++; + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _DeclareFunction.FunctionName = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("function name is expected after return type"); + } + + currentToken++; + + if (listTokens[currentToken].Equals("var")) + { + currentToken++; + DeclareVariable _DeclareVariable = new DeclareVariable(); + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _DeclareVariable.Identifier = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("variable name was expected after 'var'"); + } + + currentToken++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.EqualTo.ToString()) + { + ExceptionHandler("= sign was expected after 'var identifier'"); + } + + currentToken++; + + _DeclareVariable.Expression = ParseExpression(); + _DeclareFunction.Parameter1 = _DeclareVariable; + } + + currentToken++; + + if (listTokens[currentToken].Equals("var")) + { + currentToken++; + DeclareVariable _DeclareVariable = new DeclareVariable(); + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _DeclareVariable.Identifier = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("variable name was expected after 'var'"); + } + + currentToken++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.EqualTo.ToString()) + { + ExceptionHandler("= sign was expected after 'var identifier'"); + } + + currentToken++; + + _DeclareVariable.Expression = ParseExpression(); + + _DeclareFunction.Parameter2 = _DeclareVariable; + } + + currentToken++; + + if (listTokens[currentToken].Equals("var")) + { + currentToken++; + DeclareVariable _DeclareVariable = new DeclareVariable(); + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _DeclareVariable.Identifier = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("variable name was expected after 'var'"); + } + + currentToken++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.EqualTo.ToString()) + { + ExceptionHandler("= sign was expected after 'var identifier'"); + } + + currentToken++; + + _DeclareVariable.Expression = ParseExpression(); + + _DeclareFunction.Parameter3 = _DeclareVariable; + } + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("begin")) + { + ExceptionHandler("expected 'begin' after input parameters"); + } + + currentToken++; + _DeclareFunction.Body = ParseStatement(); + parsedStatement = _DeclareFunction; + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("endfunc")) + { + ExceptionHandler("unterminated function', 'endfunc' expected at the end"); + } + + currentToken++; + } + + else if (listTokens[currentToken].Equals("read")) + { + currentToken++; + ReadInput _ReadInput = new ReadInput(); + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _ReadInput.Identifier = (string)listTokens[currentToken++]; + parsedStatement = _ReadInput; + } + else + { + ExceptionHandler("variable name is expected after 'read'"); + parsedStatement = null; + } + } + + + // IfThenElse ifThenElse = new IfThenElse(); + + // RelationalExpression relExpr = new RelationalExpression(); + // relExpr.Left = ParseExpression(); + // if (listTokens[index] == Scanner.EqualTo) + // relExpr.Operand = RelationalOperands.EqualTo; + // else if (listTokens[index] == Scanner.LessThan) + // relExpr.Operand = RelationalOperands.LessThan; + // else if (listTokens[index] == Scanner.GreaterThan) + // relExpr.Operand = RelationalOperands.GreaterThan; + // else + // { + // ExceptionHandler("expected relational operand"); + // } + + // index++; + // relExpr.Right = ParseExpression(); + // ifThenElse.If = relExpr; + // index++; + // ifThenElse.Then = ParseStatement(); + + // parsedStatement = ifThenElse; + + // //index++; + + + + else if (listTokens[this.currentToken].Equals("while")) + { + currentToken++; + While _while = new While(); + + _while.LeftExpression = ParseExpression(); + + if (listTokens[currentToken].ToString() == Lexer.Tokens.EqualTo.ToString()) + _while.Operand = RelationalOperands.EqualTo; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.LessThan.ToString()) + _while.Operand = RelationalOperands.LessThan; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.GreaterThan.ToString()) + _while.Operand = RelationalOperands.GreaterThan; + currentToken++; + + _while.RightExpression = ParseExpression(); + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("do")) + { + ExceptionHandler("expected 'do' after while"); + } + currentToken++; + _while.Body = ParseStatement(); + parsedStatement = _while; + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("endwhile")) + { + ExceptionHandler("unterminated 'while', endwhile expected at the end"); + } + + currentToken++; + } + + else if (listTokens[this.currentToken].Equals("if")) + { + currentToken++; + IfThen _IfThen = new IfThen(); + + _IfThen.LeftExpression = ParseExpression(); + + if (listTokens[currentToken].ToString() == Lexer.Tokens.EqualTo.ToString()) + _IfThen.Operand = RelationalOperands.EqualTo; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.LessThan.ToString()) + _IfThen.Operand = RelationalOperands.LessThan; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.GreaterThan.ToString()) + _IfThen.Operand = RelationalOperands.GreaterThan; + currentToken++; + + _IfThen.RightExpression = ParseExpression(); + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("then")) + { + ExceptionHandler("expected 'then' after if"); + } + currentToken++; + _IfThen.ThenBody = ParseStatement(); + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("else")) + { + ExceptionHandler("'else' is expected"); + } + currentToken++; + _IfThen.ElseBody = ParseStatement(); + + parsedStatement = _IfThen; + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("endif")) + { + ExceptionHandler("unterminated 'if', endif expected at the end"); + } + + currentToken++; + } + + else if (listTokens[currentToken].Equals("for")) + { + currentToken++; + For _For = new For(); + + if (currentToken < listTokens.Count && listTokens[currentToken] is string) + { + _For.Identifier = (string)listTokens[currentToken]; + } + else + { + ExceptionHandler("expected identifier after 'for'"); + } + + currentToken++; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.EqualTo.ToString()) + { + ExceptionHandler("for missing '='"); + } + + currentToken++; + + _For.From = ParseExpression(); + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("to")) + { + ExceptionHandler("expected 'to' after for"); + } + + currentToken++; + + _For.To = ParseExpression(); + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("do")) + { + ExceptionHandler("expected 'do' after from expression in for loop"); + } + + currentToken++; + + _For.Body = ParseStatement(); + parsedStatement = _For; + + if (currentToken == listTokens.Count || !listTokens[currentToken].Equals("end")) + { + ExceptionHandler("unterminated 'for' loop body"); + } + + currentToken++; + } + + else if (listTokens[currentToken] is string) + { + // assignment + + Assignment _Assignment = new Assignment(); + _Assignment.Identifier = (string)listTokens[currentToken++]; + + if (currentToken == listTokens.Count || listTokens[currentToken].ToString() != Lexer.Tokens.EqualTo.ToString()) + { + ExceptionHandler("expected '='"); + } + + currentToken++; + + _Assignment.Expression = ParseExpression(); + parsedStatement = _Assignment; + } + else + { + ExceptionHandler("parse error at token " + currentToken + ": " + listTokens[currentToken]); + parsedStatement = null; + } + + if (currentToken < listTokens.Count && listTokens[currentToken].ToString() == Lexer.Tokens.Terminator.ToString()) + { + currentToken++; + + if (currentToken < listTokens.Count && !listTokens[currentToken].Equals("end") + && !listTokens[currentToken].Equals("else") && !listTokens[currentToken].Equals("endif") + && !listTokens[currentToken].Equals("endwhile") && !listTokens[currentToken].Equals("endfunc")) + { + StatementSequence sequence = new StatementSequence(); + sequence.Left = parsedStatement; + sequence.Right = ParseStatement(); + parsedStatement = sequence; + } + } + + return parsedStatement; + } + + private Expression ParseExpression() + { + Expression parsedExpression; + + if (currentToken == listTokens.Count) + { + ExceptionHandler("expected expression, got EOF"); + } + + if (listTokens[currentToken] is StringBuilder) + { + string value = ((StringBuilder)listTokens[currentToken++]).ToString(); + AlphaNumericValue _AlphaNumericValue = new AlphaNumericValue(); + _AlphaNumericValue.Value = value; + parsedExpression = _AlphaNumericValue; + } + else if (listTokens[currentToken] is int) + { + int intValue = (int)listTokens[currentToken++]; + NumericValue _NumericValue = new NumericValue(); + _NumericValue.Value = intValue; + parsedExpression = _NumericValue; + } + else if (listTokens[currentToken] is string) + { + string identifier = (string)listTokens[currentToken++]; + Identifier _Identifier = new Identifier(); + _Identifier.IdentifierName = identifier; + parsedExpression = _Identifier; + } + else + { + ExceptionHandler("expected string literal, int literal, or variable"); + return null; + } + + //if (index < listTokens.Count && listTokens[index] != Scanner.Terminator && listTokens[index].GetType() != typeof(StringBuilder)) + if (listTokens[currentToken].ToString() != Lexer.Tokens.Terminator.ToString()) + { + if (listTokens[currentToken].ToString() == Lexer.Tokens.Add.ToString() || listTokens[currentToken].ToString() == Lexer.Tokens.Subtract.ToString() + || listTokens[currentToken].ToString() == Lexer.Tokens.Multiply.ToString() || listTokens[currentToken].ToString() == Lexer.Tokens.Divide.ToString()) + { + ArithmaticExpression arithmaticExpression = new ArithmaticExpression(); + arithmaticExpression.Left = parsedExpression; + if (listTokens[currentToken].ToString() == Lexer.Tokens.Add.ToString()) + arithmaticExpression.Operand = ArithmaticOperands.Add; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.Subtract.ToString()) + arithmaticExpression.Operand = ArithmaticOperands.Subtract; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.Multiply.ToString()) + arithmaticExpression.Operand = ArithmaticOperands.Multiply; + else if (listTokens[currentToken].ToString() == Lexer.Tokens.Divide.ToString()) + arithmaticExpression.Operand = ArithmaticOperands.Division; + currentToken++; + + arithmaticExpression.Right = ParseExpression(); + parsedExpression = arithmaticExpression; + } + } + return parsedExpression; + } +} diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Program.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Program.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Text; + +// Added +using System.IO; +using System.Diagnostics; + +namespace MCG_CS +{ + class Program + { + static void Main(string[] args) + { + bool bExit = false; + + while (bExit == false) + { + Console.WriteLine("\nPlease enter the file path or type quit to exit the application"); + string strFileName = Console.ReadLine(); + + if (strFileName == "quit") + bExit = true; + else + { + + try + { + + Stopwatch timerParser = new Stopwatch(); + Stopwatch timerCompiler = new Stopwatch(); + + + + //string strInputCodeFile = "Factorial.kcl"; + + //string strFileName = "C:\\Users\\fahad\\Desktop\\MCG-CS\\Code\\" + strInputCodeFile; + + timerParser.Start(); + TextReader inputFile = File.OpenText(strFileName); + Lexer _Lexer = new Lexer(inputFile); + + IList lexemes = _Lexer.GetLexemes; + Parser parser = new Parser(lexemes); + + Console.WriteLine("\nParsing Time: " + (timerParser.ElapsedTicks).ToString()); + + timerCompiler.Start(); + + strFileName = Path.GetFileNameWithoutExtension(strFileName); + CodeGenerator codeGenerator = new CodeGenerator(parser.GetParsedStatement, strFileName + ".exe"); + + timerParser.Stop(); + timerCompiler.Stop(); + + + Console.WriteLine("Compiling Time: " + (timerCompiler.ElapsedTicks).ToString()); + Console.WriteLine("Overall Time: " + (timerParser.ElapsedTicks).ToString()); + + Console.WriteLine("\nCode has been compiled successfully!"); + Console.WriteLine("\nAn executable assembly file has been generated with the same name as input file and saved in BIN\\DEBUG folder"); + + + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + Console.WriteLine("\nPress any key to continue..."); + } + + } + } + } + } +} diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Properties/AssemblyInfo.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Properties/AssemblyInfo.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MCG-CS")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MCG-CS")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5df7bd7a-49cf-4d1e-8b45-753f17828207")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/Scanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/Scanner.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Text; +//Added +using System.IO; + +public sealed class Lexer +{ + private readonly IList listLexemes; + + public Lexer(TextReader inputFile) + { + listLexemes = new List(); + ReadProgramFile(inputFile); + } + + public IList GetLexemes + { + get + { + return listLexemes; + } + } + + public enum Tokens + { + Add, + Subtract, + Multiply, + Divide, + Terminator, + EqualTo, + LessThan, + GreaterThan, + Comma, + OpenParen, + CloseParen, + OpenBrac, + CloseBrac + } + + private void ReadProgramFile(System.IO.TextReader programFile) + { + while (programFile.Peek() != -1) + { + char symbol = (char)programFile.Peek(); + + if (char.IsWhiteSpace(symbol)) + { + // if the symbol is whitespace then move to next symbol + programFile.Read(); + } + else if (char.IsLetter(symbol) || symbol == '_') + { + //identify the tokens + + StringBuilder token = new StringBuilder(); + + while (char.IsLetter(symbol) || symbol == '_') + { + token.Append(symbol); + programFile.Read(); + + if (programFile.Peek() == -1) + { + break; + } + else + { + symbol = (char)programFile.Peek(); + } + } + + listLexemes.Add(token.ToString()); + } + else if (symbol == '"') + { + // string literal + StringBuilder stringLiteral = new StringBuilder(); + + programFile.Read(); // skip the '"' + + if (programFile.Peek() == -1) + { + throw new Exception("String literal is not terminated"); + } + + while ((symbol = (char)programFile.Peek()) != '"') + { + stringLiteral.Append(symbol); + programFile.Read(); + + if (programFile.Peek() == -1) + { + throw new Exception("String literal is not terminated"); + } + } + + // skip the terminating " + programFile.Read(); + listLexemes.Add(stringLiteral); + } + else if (char.IsDigit(symbol)) + { + // numeric literal + + StringBuilder numericLiteral = new StringBuilder(); + + while (char.IsDigit(symbol)) + { + numericLiteral.Append(symbol); + programFile.Read(); + + if (programFile.Peek() == -1) + { + break; + } + else + { + symbol = (char)programFile.Peek(); + } + } + + listLexemes.Add(int.Parse(numericLiteral.ToString())); + } + else switch (symbol) + { + case '(': + programFile.Read(); + listLexemes.Add(Tokens.OpenParen); + break; + + case ')': + programFile.Read(); + listLexemes.Add(Tokens.CloseParen); + break; + + case '=': + programFile.Read(); + listLexemes.Add(Tokens.EqualTo); + break; + + case ';': + programFile.Read(); + listLexemes.Add(Tokens.Terminator); + break; + + case '<': + programFile.Read(); + listLexemes.Add(Tokens.LessThan); + break; + + case '>': + programFile.Read(); + listLexemes.Add(Tokens.GreaterThan); + break; + + case ',': + programFile.Read(); + listLexemes.Add(Tokens.Comma); + break; + + case '/': + programFile.Read(); + listLexemes.Add(Tokens.Divide); + break; + + case '*': + programFile.Read(); + listLexemes.Add(Tokens.Multiply); + break; + + case '-': + programFile.Read(); + listLexemes.Add(Tokens.Subtract); + break; + + case '+': + programFile.Read(); + listLexemes.Add(Tokens.Add); + break; + + case '{': + programFile.Read(); + listLexemes.Add(Tokens.OpenBrac); + break; + + case '}': + programFile.Read(); + listLexemes.Add(Tokens.CloseBrac); + break; + + default: + ExceptionHandler("unidentified symbol '" + symbol + "'"); + break; + } + } + } + + public void ExceptionHandler(string strException) + { + throw new Exception(strException); + } +} diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/readme.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/readme.txt Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,13 @@ +Visual Studio 2010 is required to open this project. + +The project executable is saved in BIB\DEBUG folder with the name of MCG-CS.exe + +To generate an assembly file, run the project executable and provide the input code file path. Input file should be saved with an extension of *.kcl + +The generated assembly is saved inside "Bin\Debug\" folder. Assemblies are saved as an executable files and can be executed directly + +ILDASM.exe comand line tool is required to inspect the assembly. This tool is available in "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\" folder + +Sample code for some standard programing problems is given in CODE folder + +PROPERTIES, OBJ and BIN folders are auto-generated folders created by .NET runtime and shall not be modified