diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e4b172 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +.vs diff --git a/Compiler.sln b/Compiler.sln new file mode 100644 index 0000000..06860a7 --- /dev/null +++ b/Compiler.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compiler", "LineParser\Compiler.csproj", "{C58A9D4D-2F9B-405D-BE58-27163A50CF5F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/LineParser/Compiler.csproj b/LineParser/Compiler.csproj new file mode 100644 index 0000000..9a4fa03 --- /dev/null +++ b/LineParser/Compiler.csproj @@ -0,0 +1,185 @@ + + + + Debug + AnyCPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F} + Library + LineParser + LineParser + v3.5 + 8.0.30703 + 2.0 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LineParser/Compiler.csproj.user b/LineParser/Compiler.csproj.user new file mode 100644 index 0000000..6cbe588 --- /dev/null +++ b/LineParser/Compiler.csproj.user @@ -0,0 +1,6 @@ + + + + ProjectFiles + + \ No newline at end of file diff --git a/LineParser/Compiler.sln b/LineParser/Compiler.sln new file mode 100644 index 0000000..11e1040 --- /dev/null +++ b/LineParser/Compiler.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compiler", "Compiler.csproj", "{C58A9D4D-2F9B-405D-BE58-27163A50CF5F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C58A9D4D-2F9B-405D-BE58-27163A50CF5F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/LineParser/Compiler.userprefs b/LineParser/Compiler.userprefs new file mode 100644 index 0000000..b1d3b7a --- /dev/null +++ b/LineParser/Compiler.userprefs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LineParser/ErrorHandler/ErrorMessage.cs b/LineParser/ErrorHandler/ErrorMessage.cs new file mode 100644 index 0000000..a7bcec2 --- /dev/null +++ b/LineParser/ErrorHandler/ErrorMessage.cs @@ -0,0 +1,58 @@ +using System; +using Runtime; + +namespace ErrorHandler +{ + + public class ErrorMessage + { + public static Action errorMessageMethod; + internal static Language currentLanguage; + + internal static void sendErrorMessage(int lineNumber, string message){ + errorMessageMethod.Invoke (lineNumber, message); + } + + [System.Obsolete("Use new sendErrorMessage() instead.", true)] + internal static void sendErrorMessage(int lineNumber, ErrorType theErrorType, int index, string[] args){ + //string message = currentLanguage.getErrorMessage (theErrorType, index, args); + string message = "Message sent via old system..."; + sendErrorMessage (lineNumber, message); + } + + #region test + internal static void sendErrorMessage(int lineNumber, ErrorType errorType, string specificError, string[] args){ + string message = currentLanguage.getErrorMessage (errorType, specificError, args); + sendErrorMessage (lineNumber, message); + } + #endregion + + public static void setLanguage(){ + currentLanguage = new SwedishLanguage (); + IErrorSender theSender = (currentLanguage as IErrorSender); + + IfStatementErrors ifError = theSender.ifStatementErrors; + ElseStatementErrors elseError = theSender.elseStatementErrors; + ForLoopErrors forError = theSender.forLoopErrors; + IndentationErrors indentError = theSender.indentErrors; + TextErrors txtError = theSender.textErrors; + VariableErrors varError = theSender.variableErrors; + + WhileLoopErrors whileError = theSender.whileLoopErrors; + NumberErrors numError = theSender.numberErrors; + KeywordErrors keywordError = theSender.keywordErrors; + FunctionErrors funcError = theSender.functionErrors; + OtherErrors otherError = theSender.otherErrors; + SystemFailureErrors systemErrors = theSender.systemErrors; + + currentLanguage.initLanguageErrors1 (ifError, elseError, forError, indentError, txtError, varError); + currentLanguage.initLanguageErrors2 (whileError, numError, keywordError, funcError, otherError, systemErrors); + } + + public static void setErrorMethod(Action errorMethod){ + errorMessageMethod = errorMethod; + } + + } +} + diff --git a/LineParser/ErrorHandler/ErrorType.cs b/LineParser/ErrorHandler/ErrorType.cs new file mode 100644 index 0000000..27e2f45 --- /dev/null +++ b/LineParser/ErrorHandler/ErrorType.cs @@ -0,0 +1,22 @@ +using System; + +namespace ErrorHandler +{ + public enum ErrorType + { + ForLoop, + WhileLoop, + Variable, + Function, + IfStatements, + ElseStatements, + Expression, + Indentation, + Text, + Number, + Keyword, + Other, + System + } +} + diff --git a/LineParser/ErrorHandler/Errors/ElseError/ElseErrorType.cs b/LineParser/ErrorHandler/Errors/ElseError/ElseErrorType.cs new file mode 100644 index 0000000..34735cc --- /dev/null +++ b/LineParser/ErrorHandler/Errors/ElseError/ElseErrorType.cs @@ -0,0 +1,13 @@ +using System; + +namespace ErrorHandler +{ + public enum ElseErrorType + { + missingIndentOperator, + unknownFormat, + missingIfBeforeElse, + elseCantLinkToElse + } +} + diff --git a/LineParser/ErrorHandler/Errors/ElseError/ElseStatementErrors.cs b/LineParser/ErrorHandler/Errors/ElseError/ElseStatementErrors.cs new file mode 100644 index 0000000..1c8b381 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/ElseError/ElseStatementErrors.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface ElseStatementErrors + { + string missingIndentOperator (string[] arg); + string unknownFormat (string[] arg); + string missingIfBeforeElse (string[] arg); + string elseCantLinkToElse (string[] arg); + } + + + public class ElseErrorsOrder + { + public static Dictionary> getMessages(ElseStatementErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (ElseErrorType.missingIndentOperator.ToString(), theLogicOrder.missingIndentOperator); + messages.Add (ElseErrorType.unknownFormat.ToString(), theLogicOrder.unknownFormat); + messages.Add (ElseErrorType.missingIfBeforeElse.ToString(), theLogicOrder.missingIfBeforeElse); + messages.Add (ElseErrorType.elseCantLinkToElse.ToString(), theLogicOrder.elseCantLinkToElse); + + return messages; + } + } +} + diff --git a/LineParser/ErrorHandler/Errors/Error.cs b/LineParser/ErrorHandler/Errors/Error.cs new file mode 100644 index 0000000..553f13a --- /dev/null +++ b/LineParser/ErrorHandler/Errors/Error.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public class Error + { + private ForLoopErrorType forType; + private TextErrorType textType; + + public Error (TextErrorType eType) + { + textType = eType; + } + + public Error (ForLoopErrorType eType) + { + forType = eType; + } + + /*public Error (TextErrorType eType) + { + errorType = eType; + }*/ + } +} + diff --git a/LineParser/ErrorHandler/Errors/ForLoopError/ForLoopErrorType.cs b/LineParser/ErrorHandler/Errors/ForLoopError/ForLoopErrorType.cs new file mode 100644 index 0000000..19c5840 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/ForLoopError/ForLoopErrorType.cs @@ -0,0 +1,17 @@ +using System; + +namespace ErrorHandler +{ + public enum ForLoopErrorType { + missingIndentOperator, + unknownFormat, + expectVariableAt2, + expectInAt3, + expectRangeAt4, + rangeArgumentEmpty, + rangeArgumentNotNumber, + rangeMissingParenthesis, + counterVariableIsNotNumber + } +} + diff --git a/LineParser/ErrorHandler/Errors/ForLoopError/ForLoopErrors.cs b/LineParser/ErrorHandler/Errors/ForLoopError/ForLoopErrors.cs new file mode 100644 index 0000000..39c4d37 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/ForLoopError/ForLoopErrors.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface ForLoopErrors + { + string missingIndentOperator (string[] arg); + string unknownFormat (string[] arg); + string expectVariableAt2 (string[] arg); + string expectInAt3 (string[] arg); + string expectRangeAt4 (string[] arg); + string rangeArgumentEmpty (string[] arg); + string rangeArgumentNotNumber (string[] arg); + string rangeMissingParenthesis (string[] arg); + string counterVariableIsNotNumber (string[] arg); + } + + + + public class ForErrorsOrder + { + [System.Obsolete("Use getMessages() instead", true)] + public static Func[] getStatements(ForLoopErrors theLogicOrder){ + List> statements = new List> (); + + statements.Add (theLogicOrder.missingIndentOperator); + statements.Add (theLogicOrder.unknownFormat); + statements.Add (theLogicOrder.expectVariableAt2); + statements.Add (theLogicOrder.expectInAt3); + statements.Add (theLogicOrder.expectRangeAt4); + statements.Add (theLogicOrder.rangeArgumentEmpty); + statements.Add (theLogicOrder.rangeArgumentNotNumber); + statements.Add (theLogicOrder.rangeMissingParenthesis); + statements.Add (theLogicOrder.counterVariableIsNotNumber); + + return statements.ToArray (); + } + + #region test + + public static Dictionary> getMessages(ForLoopErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (ForLoopErrorType.missingIndentOperator.ToString(), theLogicOrder.missingIndentOperator); + messages.Add (ForLoopErrorType.unknownFormat.ToString(), theLogicOrder.unknownFormat); + messages.Add (ForLoopErrorType.expectVariableAt2.ToString(), theLogicOrder.expectVariableAt2); + messages.Add (ForLoopErrorType.expectInAt3.ToString(), theLogicOrder.expectInAt3); + messages.Add (ForLoopErrorType.expectRangeAt4.ToString(), theLogicOrder.expectRangeAt4); + messages.Add (ForLoopErrorType.rangeArgumentEmpty.ToString(), theLogicOrder.rangeArgumentEmpty); + messages.Add (ForLoopErrorType.rangeArgumentNotNumber.ToString(), theLogicOrder.rangeArgumentNotNumber); + messages.Add (ForLoopErrorType.rangeMissingParenthesis.ToString(), theLogicOrder.rangeMissingParenthesis); + messages.Add (ForLoopErrorType.counterVariableIsNotNumber.ToString(), theLogicOrder.counterVariableIsNotNumber); + + return messages; + } + + #endregion + + } +} + diff --git a/LineParser/ErrorHandler/Errors/FunctionError/FunctionErrorType.cs b/LineParser/ErrorHandler/Errors/FunctionError/FunctionErrorType.cs new file mode 100644 index 0000000..f44e7ae --- /dev/null +++ b/LineParser/ErrorHandler/Errors/FunctionError/FunctionErrorType.cs @@ -0,0 +1,10 @@ +using System; + +namespace ErrorHandler +{ + public enum FunctionErrorType + { + cantReturnFromMainScope + } +} + diff --git a/LineParser/ErrorHandler/Errors/FunctionError/FunctionErrors.cs b/LineParser/ErrorHandler/Errors/FunctionError/FunctionErrors.cs new file mode 100644 index 0000000..0530278 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/FunctionError/FunctionErrors.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface FunctionErrors + { + string cantReturnFromMainScope (string[] arg); + } + + + public class FunctionErrorsOrder + { + + public static Dictionary> getMessages(FunctionErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (FunctionErrorType.cantReturnFromMainScope.ToString(), theLogicOrder.cantReturnFromMainScope); + + return messages; + } + } +} \ No newline at end of file diff --git a/LineParser/ErrorHandler/Errors/IfAndElifError/IfErrorType.cs b/LineParser/ErrorHandler/Errors/IfAndElifError/IfErrorType.cs new file mode 100644 index 0000000..ae51bd4 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/IfAndElifError/IfErrorType.cs @@ -0,0 +1,12 @@ +using System; + +namespace ErrorHandler +{ + public enum IfErrorType + { + missingIndentOperator, + unknownFormat, + expressionNotCorrectType + } +} + diff --git a/LineParser/ErrorHandler/Errors/IfAndElifError/IfStatementErrors.cs b/LineParser/ErrorHandler/Errors/IfAndElifError/IfStatementErrors.cs new file mode 100644 index 0000000..a91adc4 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/IfAndElifError/IfStatementErrors.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + + public interface IfStatementErrors + { + string missingIndentOperator (string[] arg); + string unknownFormat (string[] arg); + string expressionNotCorrectType (string[] arg); + } + + + public class IfErrorsOrder + { + public static Dictionary> getMessages(IfStatementErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (IfErrorType.missingIndentOperator.ToString(), theLogicOrder.missingIndentOperator); + messages.Add (IfErrorType.unknownFormat.ToString(), theLogicOrder.unknownFormat); + messages.Add (IfErrorType.expressionNotCorrectType.ToString(), theLogicOrder.expressionNotCorrectType); + + return messages; + } + } + + +} + diff --git a/LineParser/ErrorHandler/Errors/IndentationError/IndentationErrorType.cs b/LineParser/ErrorHandler/Errors/IndentationError/IndentationErrorType.cs new file mode 100644 index 0000000..056361a --- /dev/null +++ b/LineParser/ErrorHandler/Errors/IndentationError/IndentationErrorType.cs @@ -0,0 +1,13 @@ +using System; + +namespace ErrorHandler +{ + public enum IndentationErrorType + { + unknownIndentStarter, + firstLineIndentError, + indentationError, + expectingBodyAfterScopeStarter + } +} + diff --git a/LineParser/ErrorHandler/Errors/IndentationError/IndentationErrors.cs b/LineParser/ErrorHandler/Errors/IndentationError/IndentationErrors.cs new file mode 100644 index 0000000..990a36a --- /dev/null +++ b/LineParser/ErrorHandler/Errors/IndentationError/IndentationErrors.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface IndentationErrors + { + string unknownIndentStarter (string[] arg); + string firstLineIndentError (string[] arg); + string indentationError (string[] arg); + string expectingBodyAfterScopeStarter (string[] arg); + + } + + + public class IndentationErrorsOrder + { + public static Dictionary> getMessages(IndentationErrors theLogicOrder) + { + Dictionary> messages = new Dictionary> (); + + messages.Add (IndentationErrorType.unknownIndentStarter.ToString(), theLogicOrder.unknownIndentStarter); + messages.Add (IndentationErrorType.firstLineIndentError.ToString(), theLogicOrder.firstLineIndentError); + messages.Add (IndentationErrorType.indentationError.ToString(), theLogicOrder.indentationError); + messages.Add (IndentationErrorType.expectingBodyAfterScopeStarter.ToString(), theLogicOrder.expectingBodyAfterScopeStarter); + + return messages; + } + } +} + + diff --git a/LineParser/ErrorHandler/Errors/KeywordError/KeywordErrorType.cs b/LineParser/ErrorHandler/Errors/KeywordError/KeywordErrorType.cs new file mode 100644 index 0000000..fdf63f6 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/KeywordError/KeywordErrorType.cs @@ -0,0 +1,9 @@ +using System; + +namespace ErrorHandler +{ + public enum KeywordErrorType + { + } +} + diff --git a/LineParser/ErrorHandler/Errors/KeywordError/KeywordErrors.cs b/LineParser/ErrorHandler/Errors/KeywordError/KeywordErrors.cs new file mode 100644 index 0000000..f413568 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/KeywordError/KeywordErrors.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface KeywordErrors + { + //string speciallDeclerationNeedsDeclaredVariable (string[] arg); + } + + + public class KeywordErrorsOrder + { + + public static Dictionary> getMessages(KeywordErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + //messages.Add (KeywordErrorType.speciallDeclerationNeedsDeclaredVariable.ToString(), theLogicOrder.speciallDeclerationNeedsDeclaredVariable); + + return messages; + } + } +} \ No newline at end of file diff --git a/LineParser/ErrorHandler/Errors/NumberError/NumberErrorType.cs b/LineParser/ErrorHandler/Errors/NumberError/NumberErrorType.cs new file mode 100644 index 0000000..15b0922 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/NumberError/NumberErrorType.cs @@ -0,0 +1,9 @@ +using System; + +namespace ErrorHandler +{ + public enum NumberErrorType + { + } +} + diff --git a/LineParser/ErrorHandler/Errors/NumberError/NumberErrors.cs b/LineParser/ErrorHandler/Errors/NumberError/NumberErrors.cs new file mode 100644 index 0000000..36282e5 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/NumberError/NumberErrors.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface NumberErrors + { + //string speciallDeclerationNeedsDeclaredVariable (string[] arg); + } + + + public class NumberErrorsOrder + { + + public static Dictionary> getMessages(NumberErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + //messages.Add (NumberErrorType.speciallDeclerationNeedsDeclaredVariable.ToString(), theLogicOrder.speciallDeclerationNeedsDeclaredVariable); + + return messages; + } + } +} \ No newline at end of file diff --git a/LineParser/ErrorHandler/Errors/OtherError/OtherErrorType.cs b/LineParser/ErrorHandler/Errors/OtherError/OtherErrorType.cs new file mode 100644 index 0000000..9f3216f --- /dev/null +++ b/LineParser/ErrorHandler/Errors/OtherError/OtherErrorType.cs @@ -0,0 +1,10 @@ +using System; + +namespace ErrorHandler +{ + public enum OtherErrorType + { + //corruptAndOrStatement + } +} + diff --git a/LineParser/ErrorHandler/Errors/OtherError/OtherErrors.cs b/LineParser/ErrorHandler/Errors/OtherError/OtherErrors.cs new file mode 100644 index 0000000..74893e7 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/OtherError/OtherErrors.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface OtherErrors + { + //string corruptAndOrStatement (string[] arg); + } + + + public class OtherErrorsOrder + { + + public static Dictionary> getMessages(OtherErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + //messages.Add (OtherErrorType.corruptAndOrStatement.ToString(), theLogicOrder.corruptAndOrStatement); + + return messages; + } + } +} \ No newline at end of file diff --git a/LineParser/ErrorHandler/Errors/SystemFailureError/SystemFailureErrorType.cs b/LineParser/ErrorHandler/Errors/SystemFailureError/SystemFailureErrorType.cs new file mode 100644 index 0000000..dd0bbb1 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/SystemFailureError/SystemFailureErrorType.cs @@ -0,0 +1,15 @@ +using System; + +namespace ErrorHandler +{ + public enum SystemFailureErrorType + { + corruptAndOrStatement, + textParsingMalfunction, + possibleComparissonStatements, + unknownLogic, + scopeParsingMalfunction, + addOrChangeUnsupportedVariableType + } +} + diff --git a/LineParser/ErrorHandler/Errors/SystemFailureError/SystemFailureErrors.cs b/LineParser/ErrorHandler/Errors/SystemFailureError/SystemFailureErrors.cs new file mode 100644 index 0000000..3667d8a --- /dev/null +++ b/LineParser/ErrorHandler/Errors/SystemFailureError/SystemFailureErrors.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface SystemFailureErrors + { + string corruptAndOrStatement (string[] arg); + string textParsingMalfunction (string[] arg); + string possibleComparissonStatements (string[] arg); + string unknownLogic (string[] arg); + string scopeParsingMalfunction (string[] arg); + string addOrChangeUnsupportedVariableType (string[] arg); + } + + public class SystemFailureErrorsOrder + { + public static Dictionary> getMessages(SystemFailureErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (SystemFailureErrorType.corruptAndOrStatement.ToString(), theLogicOrder.corruptAndOrStatement); + messages.Add (SystemFailureErrorType.textParsingMalfunction.ToString(), theLogicOrder.textParsingMalfunction); + messages.Add (SystemFailureErrorType.possibleComparissonStatements.ToString(), theLogicOrder.possibleComparissonStatements); + messages.Add (SystemFailureErrorType.unknownLogic.ToString(), theLogicOrder.unknownLogic); + messages.Add (SystemFailureErrorType.scopeParsingMalfunction.ToString(), theLogicOrder.scopeParsingMalfunction); + messages.Add (SystemFailureErrorType.addOrChangeUnsupportedVariableType.ToString(), theLogicOrder.addOrChangeUnsupportedVariableType); + + return messages; + } + } +} + diff --git a/LineParser/ErrorHandler/Errors/TextError/TextErrorType.cs b/LineParser/ErrorHandler/Errors/TextError/TextErrorType.cs new file mode 100644 index 0000000..4e0efed --- /dev/null +++ b/LineParser/ErrorHandler/Errors/TextError/TextErrorType.cs @@ -0,0 +1,12 @@ +using System; + +namespace ErrorHandler +{ + public enum TextErrorType + { + expectedPlusSignBetweenStrings, + expectedATextValue, + expressionNeedsToEndWithAString + } +} + diff --git a/LineParser/ErrorHandler/Errors/TextError/TextErrors.cs b/LineParser/ErrorHandler/Errors/TextError/TextErrors.cs new file mode 100644 index 0000000..a199b3d --- /dev/null +++ b/LineParser/ErrorHandler/Errors/TextError/TextErrors.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface TextErrors + { + string expectedPlusSignBetweenStrings(string[] arg); + string expectedATextValue(string[] arg); + string expressionNeedsToEndWithAString(string[] arg); + } + + + public class TextErrorsOrder + { + public static Dictionary> getMessages(TextErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (TextErrorType.expectedPlusSignBetweenStrings.ToString(), theLogicOrder.expectedPlusSignBetweenStrings); + messages.Add (TextErrorType.expectedATextValue.ToString(), theLogicOrder.expectedATextValue); + messages.Add (TextErrorType.expressionNeedsToEndWithAString.ToString(), theLogicOrder.expressionNeedsToEndWithAString); + + return messages; + } + } +} + + diff --git a/LineParser/ErrorHandler/Errors/VariableError/VariableErrorType.cs b/LineParser/ErrorHandler/Errors/VariableError/VariableErrorType.cs new file mode 100644 index 0000000..52cc041 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/VariableError/VariableErrorType.cs @@ -0,0 +1,10 @@ +using System; + +namespace ErrorHandler +{ + public enum VariableErrorType + { + speciallDeclerationNeedsDeclaredVariable + } +} + diff --git a/LineParser/ErrorHandler/Errors/VariableError/VariableErrors.cs b/LineParser/ErrorHandler/Errors/VariableError/VariableErrors.cs new file mode 100644 index 0000000..3572ca2 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/VariableError/VariableErrors.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface VariableErrors + { + string speciallDeclerationNeedsDeclaredVariable (string[] arg); + } + + + public class VariableErrorsOrder + { + [System.Obsolete("Use getMessages() instead", true)] + public static Func[] getStatements(VariableErrors theLogicOrder){ + List> statements = new List> (); + + statements.Add (theLogicOrder.speciallDeclerationNeedsDeclaredVariable); + + + return statements.ToArray (); + } + + public static Dictionary> getMessages(VariableErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (VariableErrorType.speciallDeclerationNeedsDeclaredVariable.ToString(), theLogicOrder.speciallDeclerationNeedsDeclaredVariable); + + return messages; + } + } +} \ No newline at end of file diff --git a/LineParser/ErrorHandler/Errors/WhileLoopError/WhileErrorType.cs b/LineParser/ErrorHandler/Errors/WhileLoopError/WhileErrorType.cs new file mode 100644 index 0000000..286ac20 --- /dev/null +++ b/LineParser/ErrorHandler/Errors/WhileLoopError/WhileErrorType.cs @@ -0,0 +1,11 @@ +using System; + +namespace ErrorHandler +{ + public enum WhileErrorType + { + missingIndentOperator, + unknownFormat + } +} + diff --git a/LineParser/ErrorHandler/Errors/WhileLoopError/WhileLoopErrors.cs b/LineParser/ErrorHandler/Errors/WhileLoopError/WhileLoopErrors.cs new file mode 100644 index 0000000..86fb22b --- /dev/null +++ b/LineParser/ErrorHandler/Errors/WhileLoopError/WhileLoopErrors.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; + +namespace ErrorHandler +{ + public interface WhileLoopErrors + { + string missingIndentOperator (string[] arg); + string unknownFormat (string[] arg); + + } + + + public class WhileErrorsOrder + { + [System.Obsolete("Use getMessages() instead", true)] + public static Func[] getStatements(WhileLoopErrors theLogicOrder){ + List> statements = new List> (); + + statements.Add (theLogicOrder.missingIndentOperator); + statements.Add (theLogicOrder.unknownFormat); + + + return statements.ToArray (); + } + + public static Dictionary> getMessages(WhileLoopErrors theLogicOrder){ + Dictionary> messages = new Dictionary> (); + + messages.Add (WhileErrorType.missingIndentOperator.ToString(), theLogicOrder.missingIndentOperator); + messages.Add (WhileErrorType.unknownFormat.ToString(), theLogicOrder.unknownFormat); + + return messages; + } + } +} + diff --git a/LineParser/ErrorHandler/IErrorSender.cs b/LineParser/ErrorHandler/IErrorSender.cs new file mode 100644 index 0000000..cc740d5 --- /dev/null +++ b/LineParser/ErrorHandler/IErrorSender.cs @@ -0,0 +1,26 @@ +using System; + +namespace ErrorHandler +{ + public interface IErrorSender { + + string getErrorMessage(ErrorType theErrorType, string theSpecificError, string[] args); + void initLanguageErrors1(IfStatementErrors If, ElseStatementErrors Else, ForLoopErrors For, IndentationErrors Indent, TextErrors Text, VariableErrors Variable); + void initLanguageErrors2(WhileLoopErrors While, NumberErrors Number, KeywordErrors Keyword, FunctionErrors Function, OtherErrors Other, SystemFailureErrors System); + + IfStatementErrors ifStatementErrors{ get; } + ElseStatementErrors elseStatementErrors{ get; } + ForLoopErrors forLoopErrors { get; } + IndentationErrors indentErrors{ get; } + TextErrors textErrors { get; } + VariableErrors variableErrors { get; } + + WhileLoopErrors whileLoopErrors{ get; } + NumberErrors numberErrors { get; } + KeywordErrors keywordErrors { get; } + FunctionErrors functionErrors { get; } + OtherErrors otherErrors { get; } + SystemFailureErrors systemErrors { get; } + } +} + diff --git a/LineParser/ErrorHandler/Languages/LanguagePrefab/Language.cs b/LineParser/ErrorHandler/Languages/LanguagePrefab/Language.cs new file mode 100644 index 0000000..4944a48 --- /dev/null +++ b/LineParser/ErrorHandler/Languages/LanguagePrefab/Language.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Runtime; + +namespace ErrorHandler +{ + + public abstract class Language{ + + + public string notFoundStatement = "Unknown Error Statement!"; + + private Dictionary>> errorMessages = new Dictionary>> (); + + + /// Inits first part of the language errors. Stores error messages in dictionary. + public void initLanguageErrors1(IfStatementErrors If, ElseStatementErrors Else, ForLoopErrors For, IndentationErrors Indent, TextErrors Text, VariableErrors Variable){ + errorMessages.Add (ErrorType.IfStatements, IfErrorsOrder.getMessages (If)); + errorMessages.Add (ErrorType.ElseStatements, ElseErrorsOrder.getMessages (Else)); + errorMessages.Add (ErrorType.ForLoop, ForErrorsOrder.getMessages (For)); + errorMessages.Add (ErrorType.Indentation, IndentationErrorsOrder.getMessages (Indent)); + errorMessages.Add (ErrorType.Text, TextErrorsOrder.getMessages (Text)); + errorMessages.Add (ErrorType.Variable, VariableErrorsOrder.getMessages (Variable)); + } + + /// Inits second part of the language errors. Stores error messages in dictionary. + public void initLanguageErrors2(WhileLoopErrors While, NumberErrors Number, KeywordErrors Keyword, FunctionErrors Function, OtherErrors Other, SystemFailureErrors system) { + errorMessages.Add (ErrorType.WhileLoop, WhileErrorsOrder.getMessages (While)); + errorMessages.Add (ErrorType.Number, NumberErrorsOrder.getMessages (Number)); + errorMessages.Add (ErrorType.Keyword, KeywordErrorsOrder.getMessages (Keyword)); + errorMessages.Add (ErrorType.Function, FunctionErrorsOrder.getMessages (Function)); + errorMessages.Add (ErrorType.Other, OtherErrorsOrder.getMessages (Other)); + errorMessages.Add (ErrorType.System, SystemFailureErrorsOrder.getMessages (system)); + } + + + /// Returns a specific error message. Second parameter must be of specific error type (e.g. ForLoopErrorType) and converted to string. + public string getErrorMessage(ErrorType theErrorType, string theSpecificError, string[] args){ + + if (errorMessages.ContainsKey (theErrorType)){ + if (errorMessages [theErrorType].ContainsKey (theSpecificError)) + return errorMessages [theErrorType] [theSpecificError].Invoke (args); + } + + return notFoundStatement; + + } + + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/AndraFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/AndraFel.cs new file mode 100644 index 0000000..d4f0fcc --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/AndraFel.cs @@ -0,0 +1,23 @@ +using System; + +namespace ErrorHandler +{ + public class AndraFel : OtherErrors + { + #region Errors from SyntaxCheck + + /*public string missingIndentOperator (string[] arg) + { + return "Det saknas ett \":\" i slutet av din Else sats"; + }*/ + + #endregion + + + + #region Errors from Runtime + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/ElseSatserFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/ElseSatserFel.cs new file mode 100644 index 0000000..ae0a13d --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/ElseSatserFel.cs @@ -0,0 +1,44 @@ +using System; + +namespace ErrorHandler +{ + public class ElseSatserFel : ElseStatementErrors + { + #region Errors from SyntaxCheck + + public string missingIndentOperator (string[] arg) + { + return "Det saknas ett \":\" i slutet av din Else sats"; + } + + /// Called if the else statement is not composed of only 2 parts. + /// An else statement should only look like "else:" + public string unknownFormat (string[] arg) + { + return "Okänt format i din Else sats. Kom ihåg att else ser ut såhär: \"else:\""; + } + + + /// Missing if before else so link can not be setup + public string missingIfBeforeElse (string[] arg) + { + return "Else måste vara länkat till en If-sats"; + } + + /// Called if there is two else after each other + public string elseCantLinkToElse (string[] arg) + { + return "Else måste komma direkt efter en If-sats. Kan inte kopplas till en annan else"; + } + + #endregion + + + + #region Errors from Runtime + + #endregion + + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/ForLoopFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/ForLoopFel.cs new file mode 100644 index 0000000..ba71ced --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/ForLoopFel.cs @@ -0,0 +1,70 @@ +using System; + +namespace ErrorHandler +{ + public class ForLoopFel : ForLoopErrors + { + + #region Errors from SyntaxCheck + /// Missings the indent operator ":". + public string missingIndentOperator (string[] args) + { + return "Det saknas ett \":\" i slutet av din for-slinga"; + } + + /// Weird format on for loop. E.g. more than 5 or less than 4 words. + public string unknownFormat (string[] args) + { + return "Okänt format på for-slingan. Kom ihåg att den ska likna: \"for i in range(5):\""; + } + + /// Expects a index variable (e.g. i) as word number 2. + public string expectVariableAt2 (string[] args) + { + return "I en for-slinga förväntas det andra ordet att vara en variabel (till exempel: i)"; + } + + /// Expects the keyword "in" as word number 3. + public string expectInAt3 (string[] args) + { + return "I en for-slinga förväntas det tredje ordet att vara \"in\""; + } + + /// Expects the keyword "range" as word number 4. This must be redefined if lists are introduced + public string expectRangeAt4 (string[] args) + { + return "I en for-slinga förväntas det fjärde ordet att vara \"range\""; + } + + #endregion + + + + #region Errors from Runtime + /// Expects atleast on number between parenthesis to range(). + public string rangeArgumentEmpty (string[] args) + { + return "Det måste finnas minst en siffra mellan parenteserna till \"range()\""; + } + + /// Expects the argsuments to range() to be numbers. + public string rangeArgumentNotNumber (string[] args) + { + return "Det får bara vara siffor mellan parenteserna till \"range()\""; + } + + /// Expects the keyword "range" to be followed by parenthesis. + public string rangeMissingParenthesis (string[] args) + { + return "Det saknas parenteser till \"range()\""; + } + + public string counterVariableIsNotNumber (string[] args) + { + return "Din räknevariabel " + args[0] + " måste vara en siffra"; + } + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/FunktionFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/FunktionFel.cs new file mode 100644 index 0000000..ecb1a3e --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/FunktionFel.cs @@ -0,0 +1,25 @@ +using System; + +namespace ErrorHandler +{ + public class FunktionFel : FunctionErrors + { + #region Errors from SyntaxCheck + + + #endregion + + + + #region Errors from Runtime + + /// Called if there is a return statement in the main scope + public string cantReturnFromMainScope (string[] arg) + { + return "Du kan inte använda return utanför en funktion"; + } + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/IfSatserFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/IfSatserFel.cs new file mode 100644 index 0000000..b0c9d2f --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/IfSatserFel.cs @@ -0,0 +1,35 @@ +using System; +namespace ErrorHandler +{ + public class IfSatserFel : IfStatementErrors + { + + #region Errors from SyntaxCheck + + public string missingIndentOperator (string[] arg) + { + return "Det saknas ett \":\" i slutet av din if-sats"; + } + + public string unknownFormat (string[] arg) + { + return "Okänt format i din if-sats. Kom ihåg att en if-sats ska likna: \"if jämförelse:\""; + } + + + #endregion + + + + #region Errors from Runtime + /// Called when expression type is not bool, number, string nor None. + /// The expression in if-statement needs to evaluate to True or False. + public string expressionNotCorrectType (string[] arg) + { + return "Uttrycket i en if-sats måste vara True (Sant) eller False (Falskt)"; + } + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/IndenteringsFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/IndenteringsFel.cs new file mode 100644 index 0000000..e75a743 --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/IndenteringsFel.cs @@ -0,0 +1,42 @@ +using System; + +namespace ErrorHandler +{ + public class IndenteringsFel : IndentationErrors + { + #region Errors from SyntaxCheck + + /// Called if there is an indentation without a scope starter (eg if, while) before + public string unknownIndentStarter (string[] arg) + { + return "Okänd start på indentering"; + } + + /// Called if first line is not at indentation level 0 + public string firstLineIndentError (string[] arg) + { + return "Första raden i programmet måste alltid vara längst till vänster."; + } + + /// Called if there is a indentation error like missing to indent after if declaration or indenting too much + public string indentationError (string[] arg) + { + return "Tabb-fel, koden måste vara rätt antal steg (tabb) in från kanten."; + } + + /// Called if there is no more lines of code after a scope starter (e.g. if, while) + public string expectingBodyAfterScopeStarter (string[] arg) + { + return "Förväntar sig indenterad kod efter den här raden"; + } + + #endregion + + + + #region Errors from Runtime + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/KeywordFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/KeywordFel.cs new file mode 100644 index 0000000..051eb4b --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/KeywordFel.cs @@ -0,0 +1,23 @@ +using System; + +namespace ErrorHandler +{ + public class KeywordFel : KeywordErrors + { + #region Errors from SyntaxCheck + + /*public string missingIndentOperator (string[] arg) + { + return "Det saknas ett \":\" i slutet av din Else sats"; + }*/ + + #endregion + + + + #region Errors from Runtime + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/NummerFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/NummerFel.cs new file mode 100644 index 0000000..850bc5b --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/NummerFel.cs @@ -0,0 +1,23 @@ +using System; + +namespace ErrorHandler +{ + public class NummerFel : NumberErrors + { + #region Errors from SyntaxCheck + + /*public string missingIndentOperator (string[] arg) + { + return "Det saknas ett \":\" i slutet av din Else sats"; + }*/ + + #endregion + + + + #region Errors from Runtime + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/SystemFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/SystemFel.cs new file mode 100644 index 0000000..e6d8150 --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/SystemFel.cs @@ -0,0 +1,51 @@ +using System; + +namespace ErrorHandler +{ + public class SystemFel : SystemFailureErrors + { + #region Errors from SyntaxCheck + + /// Called if something goes wrong in the logic when parsing. A unique error code is added to know where it got triggered + public string unknownLogic (string[] arg) + { + return "Förstår inte koden. Försök igen! (" + arg[0] + ")"; + } + + /// Called if something goes wrong with the parsing of scopes + public string scopeParsingMalfunction (string[] arg) + { + return "Något gick fel vid parsing av scopes"; + } + + #endregion + + + + #region Errors from Runtime + /// Called if (startIndex < logicOrder.Length && endIndex < logicOrder.Length) == true + /// Error could be caused by corrupt And/Or statement + public string corruptAndOrStatement (string[] arg) + { + return "Något är fel vid And/Or"; + } + + public string textParsingMalfunction (string[] arg) + { + return "Något gick galet med text-parsingen"; + } + + /// Called if parsing of a comparion in if statement fails and does not return other error + public string possibleComparissonStatements (string[] arg) + { + return "Okänt format av jämförelsen i if-satsen"; + } + + // Called if the variableType is not supported (eg unknown, unsigned) + public string addOrChangeUnsupportedVariableType(string[] arg){ + return "Typen av data du försöker lägga in i variabeln stöds inte i detta moment"; + } + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/TextFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/TextFel.cs new file mode 100644 index 0000000..ff17a95 --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/TextFel.cs @@ -0,0 +1,34 @@ +using System; + +namespace ErrorHandler +{ + public class TextFel : TextErrors + { + #region Errors from SyntaxCheck + + /// Should this error really exist? You can add strings to eachother without + in Python + public string expectedPlusSignBetweenStrings (string[] arg) + { + return "Det förväntas vara ett \"+\" mellan textsträngarna"; + } + + + + #endregion + + + + #region Errors from Runtime + public string expectedATextValue (string[] arg) + { + return "Det förväntades ett text värde"; + } + + public string expressionNeedsToEndWithAString (string[] arg) + { + return "Utrycket måste avslutas med en text"; + } + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/VariabelFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/VariabelFel.cs new file mode 100644 index 0000000..32e7ba4 --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/VariabelFel.cs @@ -0,0 +1,22 @@ +using System; + +namespace ErrorHandler +{ + public class VariabelFel : VariableErrors + { + #region Errors from SyntaxCheck + + #endregion + + + + #region Errors from Runtime + public string speciallDeclerationNeedsDeclaredVariable (string[] arg) + { + return "För att använda specialtilldelning, så måste variabeln först vara deklarerad"; + } + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishErrorTexts/WhileLoopFel.cs b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/WhileLoopFel.cs new file mode 100644 index 0000000..4acbda4 --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishErrorTexts/WhileLoopFel.cs @@ -0,0 +1,28 @@ +using System; + +namespace ErrorHandler +{ + public class WhileLoopFel : WhileLoopErrors + { + #region Errors from SyntaxCheck + + public string missingIndentOperator (string[] arg) + { + return "Det saknas ett \":\" i slutet av din While loop"; + } + + public string unknownFormat (string[] arg) + { + return "Okänt format i din While loop"; + } + + #endregion + + + + #region Errors from Runtime + + #endregion + } +} + diff --git a/LineParser/ErrorHandler/Languages/SwedishLanguage.cs b/LineParser/ErrorHandler/Languages/SwedishLanguage.cs new file mode 100644 index 0000000..84f555d --- /dev/null +++ b/LineParser/ErrorHandler/Languages/SwedishLanguage.cs @@ -0,0 +1,59 @@ +using System; + +namespace ErrorHandler +{ + public class SwedishLanguage : Language, IErrorSender + { + + public IfStatementErrors ifStatementErrors { + get {return new IfSatserFel ();} + } + + public ElseStatementErrors elseStatementErrors { + get {return new ElseSatserFel ();} + } + + public ForLoopErrors forLoopErrors { + get {return new ForLoopFel (); } + } + + public IndentationErrors indentErrors { + get {return new IndenteringsFel ();} + } + + public TextErrors textErrors { + get {return new TextFel();} + } + + public VariableErrors variableErrors { + get {return new VariabelFel ();} + } + + + + public WhileLoopErrors whileLoopErrors { + get {return new WhileLoopFel ();} + } + + public NumberErrors numberErrors { + get {return new NummerFel ();} + } + + public KeywordErrors keywordErrors { + get {return new KeywordFel ();} + } + + public FunctionErrors functionErrors { + get {return new FunktionFel ();} + } + + public OtherErrors otherErrors { + get {return new AndraFel ();} + } + + public SystemFailureErrors systemErrors { + get {return new SystemFel ();} + } + } +} + diff --git a/LineParser/ErrorHandler/LevenshteinDist.cs b/LineParser/ErrorHandler/LevenshteinDist.cs new file mode 100644 index 0000000..f1fc92e --- /dev/null +++ b/LineParser/ErrorHandler/LevenshteinDist.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Runtime; + +namespace Compiler +{ + public class LevenshteinDist + { + private static int variableMaxDist = 2; + + public static void checkForClosesVariable(string notFoundName, int lineNumber, Scope currentScope){ + List results = new List (); + + foreach (Variable v in currentScope.scopeVariables.variableList) + if (v.name != notFoundName) + results.Add (new LeveshteinResult(CalcEditDist (notFoundName, v.name), v.name)); + + results = results.OrderBy (x => x.dist).ToList (); + + + if (results.Count > 0 && results [0].dist <= variableMaxDist) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, string.Format("Hittar inte variabeln \"{0}\" i minnet.\nMenade du \"{1}\"?", notFoundName, results[0].word)); + } + + public static void checkForClosesFunctions(string notFoundName, List savedFunctions, int lineNumber) { + List results = new List(); + + foreach (Function function in savedFunctions) + if (function.name != notFoundName) + results.Add(new LeveshteinResult(CalcEditDist(notFoundName, function.name), function.name)); + + results = results.OrderBy(x => x.dist).ToList(); + + + if (results.Count > 0 && results[0].dist <= variableMaxDist) + ErrorHandler.ErrorMessage.sendErrorMessage(lineNumber, string.Format("Hittar ingen funktion med namn \"{0}\".\nMenade du \"{1}\"?", notFoundName, results[0].word)); + } + + private class LeveshteinResult{ + public int dist; + public string word; + + public LeveshteinResult(int dist, string word){ + this.dist = dist; + this.word = word; + } + } + + + /// Compute the distance between two strings. + public static int CalcEditDist(string s, string t) + { + int n = s.Length; + int m = t.Length; + int[,] d = new int[n + 1, m + 1]; + + // Step 1 + if (n == 0) + return m; + + if (m == 0) + return n; + + // Step 2 + for (int i = 0; i <= n; d[i, 0] = i++) + { + } + + for (int j = 0; j <= m; d[0, j] = j++) + { + } + + // Step 3 + for (int i = 1; i <= n; i++) + { + //Step 4 + for (int j = 1; j <= m; j++) + { + // Step 5 + int cost = (t[j - 1] == s[i - 1]) ? 0 : 1; + + // Step 6 + d[i, j] = Math.Min( + Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), + d[i - 1, j - 1] + cost); + } + } + // Step 7 + return d[n, m]; + } + } +} + diff --git a/LineParser/Functions/BuiltInFunctions/FunctionRange.cs b/LineParser/Functions/BuiltInFunctions/FunctionRange.cs new file mode 100644 index 0000000..4df3792 --- /dev/null +++ b/LineParser/Functions/BuiltInFunctions/FunctionRange.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using Compiler; + +namespace Compiler +{ + internal class FunctionRange : Function { + + public FunctionRange(){ + base.name = "range"; + base.hasReturnVariable = false; + base.inputParameterAmount.Add (1); + base.inputParameterAmount.Add (2); + base.inputParameterAmount.Add (3); + base.pauseWalker = false; + } + + + + + #region implemented abstract members of Function + public override Variable runFunction (Scope currentScope, Variable[] inputParas, int lineNumber) + { + throw new System.NotImplementedException (); + } + #endregion + } + +} + diff --git a/LineParser/Functions/BuiltInFunctions/GameFunctions.cs b/LineParser/Functions/BuiltInFunctions/GameFunctions.cs new file mode 100644 index 0000000..99298c2 --- /dev/null +++ b/LineParser/Functions/BuiltInFunctions/GameFunctions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + public class GameFunctions + { + internal static List gameFunctions; + + public static void setGameFunctions(List inputList){ + gameFunctions = inputList; + } + } +} + diff --git a/LineParser/Functions/BuiltInFunctions/PreBuiltFunctionList.cs b/LineParser/Functions/BuiltInFunctions/PreBuiltFunctionList.cs new file mode 100644 index 0000000..d85ddd5 --- /dev/null +++ b/LineParser/Functions/BuiltInFunctions/PreBuiltFunctionList.cs @@ -0,0 +1,10 @@ +using System; + +namespace Compiler +{ + internal class PreBuiltFunctionList + { + internal static Function[] pythonFunctions = {new FunctionRange()}; + } +} + diff --git a/LineParser/Functions/CurrentFunctions.cs b/LineParser/Functions/CurrentFunctions.cs new file mode 100644 index 0000000..e7a1184 --- /dev/null +++ b/LineParser/Functions/CurrentFunctions.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + + public class CurrentFunctions + { + public List savedFunctions = new List(); + + public CurrentFunctions(){ + foreach (Function f in PreBuiltFunctionList.pythonFunctions) + addFunction (f); + foreach (Function f in GameFunctions.gameFunctions) + addFunction (f); + } + + + public Function getSavedFunction(string searchedFunction, int lineNumber){ + for (int i = 0; i < savedFunctions.Count; i++) + if (savedFunctions [i].name == searchedFunction) + return savedFunctions [i]; + + LevenshteinDist.checkForClosesFunctions(searchedFunction, savedFunctions, lineNumber); + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Hittar ingen funktion med namn \"" + searchedFunction + "\"."); + return null; + } + + public bool doesFunctionExist(string searchedFunction){ + foreach(Function f in savedFunctions) + if (f.name == searchedFunction) + return true; + + return false; + } + + + public void addFunction(Function newFunc){ + for (int i = savedFunctions.Count-1; i >= 0; i--) + if (savedFunctions [i].name == newFunc.name) + savedFunctions.RemoveAt (i); + + savedFunctions.Add (newFunc); + } + + + public List getShallowCopy(){ + Function[] tempArray = savedFunctions.ToArray (); + Function[] shallow = (Function[])tempArray.Clone (); + List returnList = new List (); + returnList.AddRange (shallow); + return returnList; + } + } +} + diff --git a/LineParser/Functions/Function.cs b/LineParser/Functions/Function.cs new file mode 100644 index 0000000..c97f705 --- /dev/null +++ b/LineParser/Functions/Function.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + public abstract class Function{ + + public string name; + public string buttonText; + public bool hasReturnVariable; + public bool pauseWalker; + public List inputParameterAmount = new List(); + public string[] inputParameterNames = new string[10]; + public Scope functionScope; + public bool isUserFunction = false; + + + public abstract Variable runFunction (Scope currentScope, Variable[] inputParas, int lineNumber); + } + +} + diff --git a/LineParser/Functions/FunctionParser.cs b/LineParser/Functions/FunctionParser.cs new file mode 100644 index 0000000..74f9cda --- /dev/null +++ b/LineParser/Functions/FunctionParser.cs @@ -0,0 +1,176 @@ +using System; +using ErrorHandler; +using System.Collections.Generic; +using Runtime; + +namespace Compiler +{ + public class FunctionParser{ + + public static Logic parseIntoFunctionCall(string word, int lineNumber, Scope currentScope){ + string funcName = getFunctionName (word, lineNumber); + string funcPara = getFunctionInParameter (word, lineNumber); + + return new FunctionCall (word, funcName, PackageUnWrapper.removeSurrondingParanteser(funcPara), null); + } + + + public static void linkFunctionCall(FunctionCall theFuncCall, int lineNumber, Scope currentScope){ + + Function searchedFunc = currentScope.scopeFunctions.getSavedFunction (theFuncCall.name, lineNumber); + if (searchedFunc != null){ + validParameters (theFuncCall.parameter, searchedFunc, lineNumber, currentScope); + + if (theFuncCall.returnCalculations != null) + theFuncCall.inputVariables = parseInputVariables (theFuncCall.returnCalculations, lineNumber, theFuncCall.targetFunc, currentScope); + else + theFuncCall.inputVariables = getValueOfParameters (theFuncCall.parameter, theFuncCall.targetFunc, lineNumber, currentScope, theFuncCall); + + //for (int i = 0; i < theFuncCall.inputVariables.Length; i++) { + // Print.print (theFuncCall.inputVariables [i].name + " : " + theFuncCall.inputVariables [i].getNumber ().ToString ()); + //} + + + theFuncCall.lineNumber = lineNumber; + theFuncCall.targetFunc = searchedFunc; + theFuncCall.name = searchedFunc.name; + } + + } + + + public static string getFunctionName(string functionWord, int lineNumber){ + for (int i = 0; i < functionWord.Length; i++) + if (functionWord [i] == '(') + return functionWord.Substring (0, i); + + ErrorMessage.sendErrorMessage (lineNumber, "Funktions anrop saknar en \"(\""); + return null; + } + + + public static string getFunctionInParameter(string functionWord, int lineNumber){ + for (int i = 0; i < functionWord.Length; i++) + + if (functionWord [i] == '(') + return functionWord.Substring(i, (functionWord.Length)-i); + + ErrorMessage.sendErrorMessage (lineNumber, "Funktions anrop saknar en \"(\""); + return null; + } + + + public static bool validParameters(string trimmedPara, Function calledFunction, int lineNumber, Scope currentScope){ + int paraAmount = getParameterAmount (trimmedPara, lineNumber, currentScope); + + if (calledFunction.inputParameterAmount.Contains (paraAmount) == false) + ErrorMessage.sendErrorMessage (lineNumber, "Antal parametrar matchar inte funktions definition"); + + return true; + } + + + public static Variable[] getValueOfParameters(string trimmedPara, Function calledFunction, int lineNumber, Scope currentScope, FunctionCall theFuncCall){ + string[] words = WordParser.parseWords (trimmedPara); + + if (words.Length != 0) { + Logic[] logicOrder = WordsToLogicParser.determineLogicFromWords (words, lineNumber, currentScope); + List packedLogics = convertIntoParameterLogic (words, logicOrder, lineNumber); + theFuncCall.setReturnCalculations (packedLogics); + + if (packedLogics != null) + return parseInputVariables(packedLogics, lineNumber, calledFunction, currentScope); + } + + return new Variable[0]; + } + + + private static Variable[] parseInputVariables(List packedLogics, int lineNumber, Function calledFunction, Scope currentScope){ + Variable[] inputVariables = new Variable[packedLogics.Count]; + + for (int i = 0; i < packedLogics.Count; i++) + inputVariables [i] = SumParser.parseIntoSum (packedLogics [i], lineNumber, currentScope); + + foreach (Variable v in inputVariables) + if (v.variableType == VariableTypes.unknown) + ErrorMessage.sendErrorMessage (lineNumber, "En eller flera av inparametrarna till: " + calledFunction.name + " är korrupta"); + + return inputVariables; + } + + + public static int getParameterAmount(string trimmedPara, int lineNumber, Scope currentScope){ + string[] words = WordParser.parseWords (trimmedPara); + if (words.Length == 0) + return 0; + + Logic[] logicOrder = WordsToLogicParser.determineLogicFromWords (words, lineNumber, currentScope); + List packedLogics = convertIntoParameterLogic (words, logicOrder, lineNumber); + + return packedLogics.Count; + } + + public static string[] getParameterNames(string trimmedPara, int lineNumber, Scope currentScope){ + string[] words = WordParser.parseWords (trimmedPara); + if (words.Length == 0) + return new string[0]; + + Logic[] logicOrder = WordsToLogicParser.determineLogicFromWords (words, lineNumber, currentScope); + List packedLogics = convertIntoParameterLogic (words, logicOrder, lineNumber); + + + List returnWords = new List(); + foreach (Logic[] l in packedLogics) { + if (l.Length != 1) + ErrorMessage.sendErrorMessage (lineNumber, "Du tycks ha glömt ett \",\""); + + returnWords.Add (l [0].word); + } + + + return returnWords.ToArray(); + } + + + static List convertIntoParameterLogic(string[] words, Logic[] logicOrder, int lineNumber){ + List packedLogic = new List (); + + if (logicOrder [0].currentType == WordTypes.commaSign || logicOrder [logicOrder.Length-1].currentType == WordTypes.commaSign) + ErrorMessage.sendErrorMessage (lineNumber, "Dinna komma tecke matchar inte"); + + + int lastComma = -1; + for (int i = 0; i < logicOrder.Length; i++) { + if (logicOrder [i].currentType == WordTypes.commaSign) { + + if (i == lastComma + 1) { + ErrorMessage.sendErrorMessage (lineNumber, "Två komma tecken kan inte komma direkt efter varandra"); + return null; + } else { + + List tempList = new List (); + for (int j = lastComma + 1; j < i; j++) + tempList.Add (logicOrder [j]); + + packedLogic.Add (tempList.ToArray()); + lastComma = i; + } + + } + } + + // Fix the last package should be written as a function for beautiful code later + List tempList2 = new List (); + for (int j = lastComma+1; j < logicOrder.Length; j++) + tempList2.Add (logicOrder [j]); + + packedLogic.Add (tempList2.ToArray()); + + + return packedLogic; + } + } + +} + \ No newline at end of file diff --git a/LineParser/Functions/UserFunction.cs b/LineParser/Functions/UserFunction.cs new file mode 100644 index 0000000..75f772f --- /dev/null +++ b/LineParser/Functions/UserFunction.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using Runtime; + +namespace Compiler +{ + public class UserFunction : Function { + + public Scope targetScope; + + public UserFunction(string name, Scope targetScope, int inputParaAmount){ + base.name = name; + this.targetScope = targetScope; + base.inputParameterAmount.Add (inputParaAmount); + base.isUserFunction = true; + } + + #region implemented abstract members of Function + + public override Variable runFunction (Scope currentScope, Variable[] inputParas, int lineNumber) + { + Scope targetClone = targetScope.createDeepCopy (); + ScopeReturnParser.parseScopeReturns (targetClone, targetClone); + targetClone.linkChildScopes (targetClone); + + for (int i = 0; i < base.inputParameterNames.Length && i < inputParas.Length; i++) { + inputParas [i].name = base.inputParameterNames [i]; + Print.print ("Adding: " + inputParas [i].name + " : " + inputParas [i].getNumber ()); + targetClone.scopeVariables.addVariable (inputParas [i], targetClone.scopeParser, lineNumber); + } + + foreach (Function f in currentScope.scopeFunctions.getShallowCopy()) + targetClone.scopeFunctions.addFunction (f); + + + + Runtime.CodeWalker.switchToUserFunc (currentScope, targetClone); + return new Variable("Return Variable"); + } + + #endregion + + } + +} + diff --git a/LineParser/Logics/ComparisonType.cs b/LineParser/Logics/ComparisonType.cs new file mode 100644 index 0000000..acf3cbf --- /dev/null +++ b/LineParser/Logics/ComparisonType.cs @@ -0,0 +1,16 @@ +using System; + +namespace Compiler +{ + public enum ComparisonType{ + equalsTo, + notEqualsTo, + lessThen, + lessThenOrEqualsTo, + greaterThen, + greaterThenOrEqaulsTo, + unknown + }; + +} + diff --git a/LineParser/Logics/Lines/CodeLine.cs b/LineParser/Logics/Lines/CodeLine.cs new file mode 100644 index 0000000..4c309a4 --- /dev/null +++ b/LineParser/Logics/Lines/CodeLine.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using Runtime; + +namespace Compiler +{ + + public class CodeLine + { + public int lineNumber = 0; + public int indentLevel = 0; + public string[] words; + public Logic[] logicOrder; + public Logic theCommandType; + public Logic[] returnCalculations; + public bool doParseLine = true; + + public CodeLine(int lineNumber, int indentNumber, string[] words){ + this.indentLevel = indentNumber; + this.lineNumber = lineNumber; + this.words = words; + } + + + public string getFullLine(){ + string temp = ""; + for (int i = 0; i < words.Length; i++) + temp += words [i]; + + return temp; + } + + public CodeLine cloneLine(){ + CodeLine tempLine = new CodeLine (lineNumber, indentLevel, words); + + Logic[] tempOrder = (Logic[])logicOrder.Clone (); + for (int i = 0; i < tempOrder.Length; i++) { + if (tempOrder [i].currentType == WordTypes.returnStatement) + tempOrder [i] = new ReturnStatement (); + + } + tempLine.logicOrder = tempOrder; + + tempLine.resetCalculations (); + return tempLine; + } + + + #region return calculations + public Logic[] getLatestOrder(){ + if (returnCalculations == null) + return logicOrder; + + return returnCalculations; + } + + public void resetCalculations(){ + returnCalculations = null; + } + + public void insertReturnExpect(Logic l){ + Logic[] tempLogic = (Logic[])getLatestOrder ().Clone (); + returnCalculations = tempLogic; + + ReturnMemoryControll.insertReturnExpectation (this, lineNumber, l); + } + + + + #endregion + } +} + diff --git a/LineParser/Logics/Lines/ComparisonOperatorParser.cs b/LineParser/Logics/Lines/ComparisonOperatorParser.cs new file mode 100644 index 0000000..90ea8ed --- /dev/null +++ b/LineParser/Logics/Lines/ComparisonOperatorParser.cs @@ -0,0 +1,166 @@ +using System; +using ErrorHandler; + +namespace Compiler +{ + public class ComparisonOperatorParser{ + + public static ComparisonType parseOperators(Logic[] logicOrder){ + + if (logicOrder.Length > 2 || logicOrder.Length == 0) + return ComparisonType.unknown; + + + if (logicOrder.Length == 1) + return parseSingleOperator (logicOrder [0]); + + if (logicOrder.Length == 2) + return parseSDoubleOperator (logicOrder); + + return ComparisonType.unknown; + } + + static ComparisonType parseSDoubleOperator(Logic[] theOperators){ + if (theOperators[1].currentType != WordTypes.equalSign) + return ComparisonType.unknown; + + + if (theOperators[0].currentType == WordTypes.equalSign) + return ComparisonType.equalsTo; + + if (theOperators[0].currentType == WordTypes.lessThenSign) + return ComparisonType.lessThenOrEqualsTo; + + if (theOperators[0].currentType == WordTypes.greaterThenSign) + return ComparisonType.greaterThenOrEqaulsTo; + + if (theOperators[0].currentType == WordTypes.xorOperator) + return ComparisonType.notEqualsTo; + + + return ComparisonType.unknown; + } + + + static ComparisonType parseSingleOperator(Logic theOperator){ + if (theOperator.currentType == WordTypes.lessThenSign) + return ComparisonType.lessThen; + + if (theOperator.currentType == WordTypes.greaterThenSign) + return ComparisonType.greaterThen; + + return ComparisonType.unknown; + } + + + + + public static bool checkSumsToOperator(VariableTypes theSum, ComparisonType theOperator, int lineNumber){ + if (theSum == VariableTypes.number) + return true; + + if (theSum == VariableTypes.boolean) { + if (theOperator == ComparisonType.equalsTo || theOperator == ComparisonType.notEqualsTo) + return true; + } + + if (theSum == VariableTypes.textString) { + if (theOperator == ComparisonType.equalsTo || theOperator == ComparisonType.notEqualsTo) + return true; + } + + + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Okänd operator kombination av " + theSum); + return false; + } + + public static bool makeComparison(Variable var1, Variable var2, ComparisonType theOperator, int lineNumber){ + + if (var1.variableType == VariableTypes.unknown || var1.variableType == VariableTypes.unsigned || var2.variableType == VariableTypes.unknown || var2.variableType == VariableTypes.unsigned) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "En eller flera av operatorerna går inte att tyda"); + + + if (var1.variableType != var2.variableType) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Kan inte utföra jämförelse mellan " + var1.variableType + " och " + var2.variableType); + + + if (theOperator == ComparisonType.equalsTo) { + if (var1.variableType == VariableTypes.boolean) { + if (var1.getBool () == var2.getBool ()) + return true; + else + return false; + } + + if (var1.variableType == VariableTypes.number) { + if (var1.getNumber () == var2.getNumber ()) + return true; + else + return false; + } + + if (var1.variableType == VariableTypes.textString) { + if (var1.getString () == var2.getString ()) + return true; + else + return false; + } + } + + if (theOperator == ComparisonType.notEqualsTo) { + if (var1.variableType == VariableTypes.boolean) { + if (var1.getBool () != var2.getBool ()) + return true; + else + return false; + } + + if (var1.variableType == VariableTypes.number) { + if (var1.getNumber () != var2.getNumber ()) + return true; + else + return false; + } + + if (var1.variableType == VariableTypes.textString) { + if (var1.getString () != var2.getString ()) + return true; + else + return false; + } + } + + if (theOperator == ComparisonType.greaterThenOrEqaulsTo && var1.variableType == VariableTypes.number){ + if (var1.getNumber () >= var2.getNumber ()) + return true; + else + return false; + } + + if (theOperator == ComparisonType.lessThenOrEqualsTo && var1.variableType == VariableTypes.number){ + if (var1.getNumber () <= var2.getNumber ()) + return true; + else + return false; + } + if (theOperator == ComparisonType.lessThen && var1.variableType == VariableTypes.number){ + if (var1.getNumber () < var2.getNumber ()) + return true; + else + return false; + } + if (theOperator == ComparisonType.greaterThen && var1.variableType == VariableTypes.number){ + if (var1.getNumber () > var2.getNumber ()) + return true; + else + return false; + } + + + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.unknownLogic.ToString(), new string[]{"4"}); + return false; + } + } + +} + diff --git a/LineParser/Logics/Lines/ReturnValue.cs b/LineParser/Logics/Lines/ReturnValue.cs new file mode 100644 index 0000000..7748f1d --- /dev/null +++ b/LineParser/Logics/Lines/ReturnValue.cs @@ -0,0 +1,13 @@ +using System; + +namespace Compiler +{ + public class ReturnValue : Logic + { + public ReturnValue(){ + base.currentType = WordTypes.returnValue; + base.word = "returnValue"; + } + } +} + diff --git a/LineParser/Logics/Logic.cs b/LineParser/Logics/Logic.cs new file mode 100644 index 0000000..72225c0 --- /dev/null +++ b/LineParser/Logics/Logic.cs @@ -0,0 +1,12 @@ +using System; + +namespace Compiler +{ + public abstract class Logic{ + + public string word; + public WordTypes currentType; + + } +} + diff --git a/LineParser/Logics/Loops/ForLoop.cs b/LineParser/Logics/Loops/ForLoop.cs new file mode 100644 index 0000000..c6b9148 --- /dev/null +++ b/LineParser/Logics/Loops/ForLoop.cs @@ -0,0 +1,76 @@ +using System.Collections; +using System.Collections.Generic; +using Runtime; +using ErrorHandler; + +namespace Compiler{ + + public class ForLoop : ScopeLoop, Loop{ + + public int indentLevel; + public double startValue = 0; + public double endValue; + public double incrementValue = 1; + public Variable counterVariable; + + public ForLoop(){ + base.currentType = WordTypes.forLoop; + base.word = "for"; + base.theComparisonType = ComparisonType.lessThen; + } + + public void setLoopVariables(string counterName, double startValue, double endValue, double incrementValue){ + this.startValue = startValue; + this.endValue = endValue; + + if (incrementValue < 0) { + base.theComparisonType = ComparisonType.greaterThen; + Print.print ("Changing type"); + } + + Variable leftVariable = new Variable (counterName, startValue); + Variable checkVariable = new Variable ("ForLoopCheckValue", endValue); + + this.counterVariable = leftVariable; + + counterVariable.setValue (startValue); + counterVariable.isForLoopVariable = true; + + base.leftValue = counterVariable; + base.rightValue = checkVariable; + this.incrementValue = incrementValue; + } + + + #region Loop implementation + public void addCounterVariableToScope(int lineNumber){ + getTargetScope().scopeVariables.addVariable (counterVariable, getTargetScope().scopeParser, lineNumber); + } + + public bool makeComparison (int lineNumber, bool doChangeValue = true) + { + if (counterVariable.variableType != VariableTypes.number) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.counterVariableIsNotNumber.ToString(), new string[1] {counterVariable.name}); + + if(doChangeValue) + counterVariable.setValue (counterVariable.getNumber () + incrementValue); + bool doLoop = ComparisonOperatorParser.makeComparison (counterVariable, base.rightValue, base.theComparisonType, lineNumber); + + + getTargetScope().scopeVariables.addVariable (counterVariable, getTargetScope().scopeParser, lineNumber); + if (doLoop == false && doChangeValue) + counterVariable.setValue (endValue - incrementValue); + + return doLoop; + } + + + public void resetCounterVariable () + { + counterVariable.setValue (startValue); + } + #endregion + + } + +} \ No newline at end of file diff --git a/LineParser/Logics/Loops/Loop.cs b/LineParser/Logics/Loops/Loop.cs new file mode 100644 index 0000000..ecec993 --- /dev/null +++ b/LineParser/Logics/Loops/Loop.cs @@ -0,0 +1,11 @@ +using System.Collections; + +namespace Compiler{ + + public interface Loop{ + bool makeComparison (int lineNumber, bool changeValue = true); + void addCounterVariableToScope (int lineNumber); + void resetCounterVariable(); + } + +} diff --git a/LineParser/Logics/Loops/WhileLoop.cs b/LineParser/Logics/Loops/WhileLoop.cs new file mode 100644 index 0000000..4b1647c --- /dev/null +++ b/LineParser/Logics/Loops/WhileLoop.cs @@ -0,0 +1,33 @@ +using System; + +namespace Compiler +{ + public class WhileLoop : ScopeLoop, Loop { + + public int indentLevel; + public Logic[] theStatement; + + public WhileLoop(){ + base.currentType = WordTypes.whileLoop; + base.word = "while"; + } + + #region Loop implementation + public bool makeComparison (int lineNumber, bool changeValue = true) + { + return StatementParser.parseStatement (theStatement, lineNumber, getTargetScope()); + } + + public void addCounterVariableToScope (int lineNumber) + { + + } + public void resetCounterVariable () + { + + } + #endregion + } + +} + diff --git a/LineParser/Logics/Operators/AndOperator.cs b/LineParser/Logics/Operators/AndOperator.cs new file mode 100644 index 0000000..4aea4bd --- /dev/null +++ b/LineParser/Logics/Operators/AndOperator.cs @@ -0,0 +1,15 @@ +using System.Collections; + +namespace Compiler{ + + public class AndOperator : Logic, AndOrOperator { + + public AndOperator(string word){ + base.currentType = WordTypes.andOperator; + base.word = word; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/CommaSign.cs b/LineParser/Logics/Operators/CommaSign.cs new file mode 100644 index 0000000..86966ff --- /dev/null +++ b/LineParser/Logics/Operators/CommaSign.cs @@ -0,0 +1,13 @@ +using System.Collections; + +namespace Compiler{ + + public class CommaSign : Logic{ + + public CommaSign(){ + base.currentType = WordTypes.commaSign; + base.word = ","; + } + + } +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/EqualSign.cs b/LineParser/Logics/Operators/EqualSign.cs new file mode 100644 index 0000000..7785bba --- /dev/null +++ b/LineParser/Logics/Operators/EqualSign.cs @@ -0,0 +1,14 @@ +using System.Collections; + +namespace Compiler{ + + public class EqualSign : Logic, ComparisonOperator{ + + public EqualSign(){ + base.currentType = WordTypes.equalSign; + base.word = "="; + } + + } + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/GreaterThenSign.cs b/LineParser/Logics/Operators/GreaterThenSign.cs new file mode 100644 index 0000000..34fc504 --- /dev/null +++ b/LineParser/Logics/Operators/GreaterThenSign.cs @@ -0,0 +1,15 @@ +using System.Collections; + +namespace Compiler{ + + public class GreaterThenSign : Logic, ComparisonOperator{ + + public GreaterThenSign(){ + base.currentType = WordTypes.greaterThenSign; + base.word = ">"; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/IndentOperator.cs b/LineParser/Logics/Operators/IndentOperator.cs new file mode 100644 index 0000000..77a2552 --- /dev/null +++ b/LineParser/Logics/Operators/IndentOperator.cs @@ -0,0 +1,15 @@ +using System.Collections; + +namespace Compiler{ + + public class IndentOperator : Logic{ + + public IndentOperator(){ + base.currentType = WordTypes.indentOperator; + base.word = ":"; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/LessThenSign.cs b/LineParser/Logics/Operators/LessThenSign.cs new file mode 100644 index 0000000..e6beaf0 --- /dev/null +++ b/LineParser/Logics/Operators/LessThenSign.cs @@ -0,0 +1,14 @@ +using System.Collections; + +namespace Compiler{ + + public class LessThenSign : Logic, ComparisonOperator{ + + public LessThenSign(){ + base.currentType = WordTypes.lessThenSign; + base.word = "<"; + } + + } + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/MathOperator.cs b/LineParser/Logics/Operators/MathOperator.cs new file mode 100644 index 0000000..e7ac8d6 --- /dev/null +++ b/LineParser/Logics/Operators/MathOperator.cs @@ -0,0 +1,16 @@ +using System.Collections; + +namespace Compiler{ + + public class MathOperator : Logic { + + public MathOperator(string word){ + base.currentType = WordTypes.mathOperator; + + base.word = word; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/NotOperator.cs b/LineParser/Logics/Operators/NotOperator.cs new file mode 100644 index 0000000..2b0978a --- /dev/null +++ b/LineParser/Logics/Operators/NotOperator.cs @@ -0,0 +1,16 @@ +using System.Collections; + +namespace Compiler{ + + public class NotOperator : Logic { + + public NotOperator(string word){ + base.currentType = WordTypes.notOperator; + + base.word = word; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/OrOperator.cs b/LineParser/Logics/Operators/OrOperator.cs new file mode 100644 index 0000000..569308c --- /dev/null +++ b/LineParser/Logics/Operators/OrOperator.cs @@ -0,0 +1,15 @@ +using System.Collections; + +namespace Compiler{ + + public class OrOperator : Logic, AndOrOperator { + + public OrOperator(string word){ + base.currentType = WordTypes.orOperator; + base.word = word; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Operators/XorOperator.cs b/LineParser/Logics/Operators/XorOperator.cs new file mode 100644 index 0000000..c8ba2f6 --- /dev/null +++ b/LineParser/Logics/Operators/XorOperator.cs @@ -0,0 +1,16 @@ +using System.Collections; + +namespace Compiler{ + + public class XorOperator : Logic, ComparisonOperator { + + public XorOperator(string word){ + base.currentType = WordTypes.xorOperator; + + base.word = word; + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Speciall/BreakStatement.cs b/LineParser/Logics/Speciall/BreakStatement.cs new file mode 100644 index 0000000..960ec15 --- /dev/null +++ b/LineParser/Logics/Speciall/BreakStatement.cs @@ -0,0 +1,15 @@ +using System; + +namespace Compiler +{ + public class BreakStatement : Logic{ + + public BreakStatement(){ + base.currentType = WordTypes.breakStatement; + base.word = "break"; + } + + + } +} + diff --git a/LineParser/Logics/Speciall/ContinueStatment.cs b/LineParser/Logics/Speciall/ContinueStatment.cs new file mode 100644 index 0000000..471f014 --- /dev/null +++ b/LineParser/Logics/Speciall/ContinueStatment.cs @@ -0,0 +1,14 @@ +using System; + +namespace Compiler +{ + public class ContinueStatment : Logic + { + public ContinueStatment(){ + base.currentType = WordTypes.continueStatement; + base.word = "continue"; + } + + } +} + diff --git a/LineParser/Logics/Speciall/DefStatement.cs b/LineParser/Logics/Speciall/DefStatement.cs new file mode 100644 index 0000000..b86bd0e --- /dev/null +++ b/LineParser/Logics/Speciall/DefStatement.cs @@ -0,0 +1,20 @@ +using System.Collections; + +namespace Compiler{ + + public class DefStatement : ScopeStarter { + + + public int indentLevel; + public ElseStatement linkedElse; + + public DefStatement(){ + base.currentType = WordTypes.defStatement; + base.word = "def"; + } + + + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Speciall/ElifStatement.cs b/LineParser/Logics/Speciall/ElifStatement.cs new file mode 100644 index 0000000..1dbd366 --- /dev/null +++ b/LineParser/Logics/Speciall/ElifStatement.cs @@ -0,0 +1,45 @@ +using System; + +namespace Compiler +{ + public class ElifStatement : ScopeStarter, ComparisonScope{ + + public int indentLevel; + public ComparisonScope nextStatement; + + public ElifStatement(){ + base.currentType = WordTypes.elifOperator; + base.word = "elif"; + base.doEnterScope = false; + } + + + public void initNextstatement(){ + if (nextStatement != null) { + nextStatement.setParseLine (!doEnterScope); + + if (nextStatement is ElseStatement) + nextStatement.setEnterScope (!doEnterScope); + } + } + + #region ComparisonScope implementation + + public void linkNextStatement (ComparisonScope nextScope){ + nextStatement = nextScope; + } + public void setEnterScope (bool value) + { + base.doEnterScope = value; + } + + public void setParseLine (bool value) + { + if (value == false && nextStatement != null) + nextStatement.setParseLine (false); + base.doParseLine = value; + } + #endregion + } +} + diff --git a/LineParser/Logics/Speciall/ElseStatement.cs b/LineParser/Logics/Speciall/ElseStatement.cs new file mode 100644 index 0000000..fb8b3ed --- /dev/null +++ b/LineParser/Logics/Speciall/ElseStatement.cs @@ -0,0 +1,30 @@ +using System.Collections; + +namespace Compiler{ + + public class ElseStatement : ScopeStarter, ComparisonScope{ + + public int indentLevel; + public ElseStatement(){ + base.currentType = WordTypes.elseOperator; + base.word = "else"; + } + + #region ComparisonScope implementation + public void linkNextStatement (ComparisonScope nextScope){} + public void initNextstatement (){} + + public void setEnterScope (bool value) + { + base.doEnterScope = value; + } + + public void setParseLine (bool value) + { + base.doParseLine = value; + } + #endregion + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Speciall/FunctionCall.cs b/LineParser/Logics/Speciall/FunctionCall.cs new file mode 100644 index 0000000..6124312 --- /dev/null +++ b/LineParser/Logics/Speciall/FunctionCall.cs @@ -0,0 +1,59 @@ +using System.Collections; +using System.Collections.Generic; +using Runtime; + +namespace Compiler{ + + public class FunctionCall : Logic { + + public string fullWord; + public string name; + public string parameter; + public bool hasReturnVariable; + public Function targetFunc; + public Variable[] inputVariables; + + public List returnCalculations; + + public int lineNumber; + + public FunctionCall(string fullWord, string name, string parameter, Function targetFunc){ + setLogic (word, WordTypes.functionCall); + this.fullWord = word; + this.targetFunc = targetFunc; + this.name = name; + this.parameter = parameter; + base.currentType = WordTypes.functionCall; + } + + + public Variable runFunction (Scope currentScope){ + if (CodeWalker.isWaitingForUserInput) + return new Variable(); + + return targetFunc.runFunction (currentScope, inputVariables, lineNumber); + } + + public void setLogic(string word, WordTypes currentType){ + base.currentType = currentType; + base.word = word; + } + + + #region Return Calculations + public void setReturnCalculations(List inputList){ + returnCalculations = new List (); + foreach (Logic[] l in inputList) + returnCalculations.Add (l); + } + + public void resetCalculations(){ + returnCalculations.Clear (); + returnCalculations = null; + } + + #endregion + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Speciall/IfStatement.cs b/LineParser/Logics/Speciall/IfStatement.cs new file mode 100644 index 0000000..577a34b --- /dev/null +++ b/LineParser/Logics/Speciall/IfStatement.cs @@ -0,0 +1,43 @@ +using System.Collections; + +namespace Compiler{ + + public class IfStatement : ScopeStarter, ComparisonScope { + + public int indentLevel; + public ComparisonScope nextStatement; + + public IfStatement(){ + base.currentType = WordTypes.ifOperator; + base.word = "if"; + } + + + public void initNextstatement(){ + if (nextStatement != null) { + nextStatement.setParseLine (!doEnterScope); + + if (nextStatement is ElseStatement) + nextStatement.setEnterScope (!doEnterScope); + } + } + + #region ComparisonScope implementation + public void linkNextStatement (ComparisonScope nextScope){ + nextStatement = nextScope; + } + public void setEnterScope (bool value) + { + base.doEnterScope = value; + } + + public void setParseLine (bool value) + { + base.doParseLine = value; + } + + #endregion + } + + +} \ No newline at end of file diff --git a/LineParser/Logics/Speciall/Package.cs b/LineParser/Logics/Speciall/Package.cs new file mode 100644 index 0000000..769d05b --- /dev/null +++ b/LineParser/Logics/Speciall/Package.cs @@ -0,0 +1,59 @@ +using System; + +namespace Compiler +{ + public class Package : Logic{ + + public int lineNumber = 0; + public Logic[] logicOrder; + public Logic[] returnCalculations; + + + public Package(string word, int lineNumber){ + this.lineNumber = lineNumber; + base.word = word; + base.currentType = WordTypes.package; + } + + public Package(Logic[] logicOrder, int lineNumber){ + this.lineNumber = lineNumber; + base.word = "Internal Package"; + base.currentType = WordTypes.package; + this.logicOrder = logicOrder; + } + + + + public void setLogicOrder(Logic[] logicOrder){ + this.logicOrder = logicOrder; + } + + + #region return calculations + public Logic[] getLatestOrder(){ + if (returnCalculations == null) + return logicOrder; + + return returnCalculations; + } + + public void resetCalculations(){ + returnCalculations = null; + } + + public void insertAwaitReturn(Logic l){ + Logic[] tempLogic = (Logic[])getLatestOrder ().Clone (); + + for (int i = 0; i < tempLogic.Length; i++) + if (tempLogic [i] == l) { + tempLogic [i] = new ReturnValue (); + returnCalculations = tempLogic; + return; + } + else if (tempLogic [i].currentType == WordTypes.package) + (tempLogic [i] as Package).insertAwaitReturn (l); + } + #endregion + } +} + diff --git a/LineParser/Logics/Speciall/ReturnStatement.cs b/LineParser/Logics/Speciall/ReturnStatement.cs new file mode 100644 index 0000000..72e0aae --- /dev/null +++ b/LineParser/Logics/Speciall/ReturnStatement.cs @@ -0,0 +1,42 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class ReturnStatement : Logic + { + public Logic[] followOrder; + public Scope FunctionParent; + + + public ReturnStatement () + { + base.currentType = WordTypes.returnStatement; + base.word = "return"; + } + + + public void findFunctionParent(Scope currentScope, int lineNumber){ + if (currentScope.theScopeType == ScopeType.function) { + return; + } + else if(currentScope.theScopeType == ScopeType.main) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.Function, FunctionErrorType.cantReturnFromMainScope.ToString(), null); + + + if(currentScope.parentScope == null) + ErrorMessage.sendErrorMessage (lineNumber, "Scope saknar anropare \n" + currentScope.theScopeType); + + + Scope parentScope = currentScope.parentScope; + while (parentScope.theScopeType != ScopeType.function) { + parentScope = parentScope.parentScope; + } + FunctionParent = parentScope; + } + + + } +} + diff --git a/LineParser/Logics/WordTypes.cs b/LineParser/Logics/WordTypes.cs new file mode 100644 index 0000000..d0d920b --- /dev/null +++ b/LineParser/Logics/WordTypes.cs @@ -0,0 +1,37 @@ +namespace Compiler{ + + public enum WordTypes{ + variable, + functionCall, + mathOperator, + number, + textString, + booleanValue, + booleanExpression, + ifOperator, + elseOperator, + elifOperator, + forLoop, + whileLoop, + defStatement, + breakStatement, + continueStatement, + returnStatement, + returnValue, + equalSign, + xorOperator, + lessThenSign, + greaterThenSign, + notOperator, + andOperator, + orOperator, + speciallWord, + inWord, + indentOperator, + commaSign, + package, // A package is a compressed parameter example: (x + 23 - 3) + nill, + unknown, + }; + +} \ No newline at end of file diff --git a/LineParser/PackageUnWrapper.cs b/LineParser/PackageUnWrapper.cs new file mode 100644 index 0000000..e3c3b14 --- /dev/null +++ b/LineParser/PackageUnWrapper.cs @@ -0,0 +1,28 @@ +using System; + +namespace Compiler +{ + public class PackageUnWrapper{ + + public static void unpackPackage(string word, int lineNumber, Scope currentScope, Package currentPackage){ + + if (word.Length <= 2) + return; + + string trimedString = removeSurrondingParanteser(word); + + string[] words = WordParser.parseWords (trimedString); + Logic[] logicOrder = WordsToLogicParser.determineLogicFromWords (words, lineNumber, currentScope); + + currentPackage.logicOrder = logicOrder; + } + + + + public static string removeSurrondingParanteser(string word){ + return word.Substring (1, word.Length - 2); + } + + } +} + diff --git a/LineParser/Parsers/AndOperatorParser.cs b/LineParser/Parsers/AndOperatorParser.cs new file mode 100644 index 0000000..cf24187 --- /dev/null +++ b/LineParser/Parsers/AndOperatorParser.cs @@ -0,0 +1,12 @@ +using System; + + +namespace Compiler +{ + public class AndOperatorParser + { + + + } +} + diff --git a/LineParser/Parsers/BooleanAlgebra/FindBoolExpressions.cs b/LineParser/Parsers/BooleanAlgebra/FindBoolExpressions.cs new file mode 100644 index 0000000..5ff4662 --- /dev/null +++ b/LineParser/Parsers/BooleanAlgebra/FindBoolExpressions.cs @@ -0,0 +1,12 @@ +using System; + +namespace LineParser +{ + public class FindBoolExpressions + { + public FindBoolExpressions () + { + } + } +} + diff --git a/LineParser/Parsers/FunctionParser.cs b/LineParser/Parsers/FunctionParser.cs new file mode 100644 index 0000000..807d570 --- /dev/null +++ b/LineParser/Parsers/FunctionParser.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + public class FunctionParser{ + + public static Compiler.Logic parseIntoFunctionCall(string word, int lineNumber, Compiler.Scope currentScope){ + + string funcName = getFunctionName (word, lineNumber); + string funcPara = getFunctionInParameter (word, lineNumber); + + return new FunctionCall (word, funcName, funcPara, null); + } + + public static void linkFunctionCall(FunctionCall theFunc, int lineNumber, Compiler.Scope currentScope){ + Compiler.Function searchedFunc = currentScope.scopeFunctions.getSavedFunction (theFunc.name, lineNumber); + if (searchedFunc != null){ + + Compiler.Variable[] inputVariables = validParameters (PackageUnWrapper.removeSurrondingParanteser (theFunc.parameter), searchedFunc, lineNumber, currentScope); + theFunc.targetFunc = searchedFunc; + } + + } + + + public static string getFunctionName(string functionWord, int lineNumber){ + + for (int i = 0; i < functionWord.Length; i++) + if (functionWord [i] == '(') + return functionWord.Substring (0, i); + + ErrorMessage.sendErrorMessage (lineNumber, "Compiler.Function Call is missing a ("); + return null; + } + + + public static string getFunctionInParameter(string functionWord, int lineNumber){ + + for (int i = 0; i < functionWord.Length; i++) + + if (functionWord [i] == '(') + return functionWord.Substring(i, (functionWord.Length)-i); + + ErrorMessage.sendErrorMessage (lineNumber, "Compiler.Function Call is missing a ("); + return null; + } + + + public static bool hasReturnValue(string word, int lineNumber){ + Compiler.Function searchedFunc = Camera.main.GetComponent().funcs.getSavedFunction (FunctionParser.getFunctionName (word, lineNumber), lineNumber); + if (searchedFunc != null) + return searchedFunc.hasReturnVariable; + + + return false; + } + + + + static Compiler.Variable[] validParameters(string trimmedPara, Compiler.Function calledFunction, int lineNumber, Compiler.Scope currentScope){ + + + string[] words = Compiler.WordParser.parseWords (trimmedPara); + + if (words.Length != 0) { + Compiler.Logic[] logicOrder = WordLogic.determineLogicFromWords (words, lineNumber, currentScope); + + List> packedLogics = convertIntoParameterLogic (words, logicOrder, lineNumber); + + if (packedLogics != null) { + Compiler.Variable[] inputVariables = new Compiler.Variable[packedLogics.Count]; + + for (int i = 0; i < packedLogics.Count; i++) + inputVariables [i] = ValidSumCheck.checkIfValidSum (packedLogics [i].ToArray (), lineNumber); + + + foreach (Compiler.Variable v in inputVariables) + if (v.variableType == Compiler.VariableTypes.unkown) + ErrorMessage.sendErrorMessage (lineNumber, "one or several of the input parameters to function: " + calledFunction.name + " are corrupt!"); + + + if (calledFunction.inputParameters.Contains (inputVariables.Length)) + return inputVariables; + } + + } + + if (calledFunction.inputParameters.Contains (0)) + return new Compiler.Variable[0]; + + ErrorMessage.sendErrorMessage (lineNumber, "Amount of parameters does not match Expected!"); + return new Compiler.Variable[0]; + } + + + public static Compiler.Variable[] getValueOfParameters(string trimmedPara, Compiler.Function calledFunction, int lineNumber,Compiler.Scope currentScope){ + + + string[] words = Compiler.WordParser.parseWords (trimmedPara); + + if (words.Length != 0) { + Compiler.Logic[] logicOrder = WordLogic.determineLogicFromWords (words, lineNumber, currentScope); + + List> packedLogics = convertIntoParameterLogic (words, logicOrder, lineNumber); + + if (packedLogics != null) { + Compiler.Variable[] inputVariables = new Compiler.Variable[packedLogics.Count]; + + for (int i = 0; i < packedLogics.Count; i++) + inputVariables [i] = SumParser.parseIntoSum (packedLogics [i].ToArray (), lineNumber, currentScope); + + + foreach (Compiler.Variable v in inputVariables) + if (v.variableType == Compiler.VariableTypes.unkown) + ErrorMessage.sendErrorMessage (lineNumber, "one or several of the input parameters to function: " + calledFunction.name + " are corrupt!"); + + + if (calledFunction.inputParameters.Contains (inputVariables.Length)) + return inputVariables; + } + + } + + return new Compiler.Variable[0]; + } + + + + static List> convertIntoParameterLogic(string[] words, Compiler.Logic[] logicOrder, int lineNumber){ + + List> packedLogic = new List> (); + + + + if (logicOrder [0].currentType == Compiler.WordTypes.commaSign || logicOrder [logicOrder.Length-1].currentType == Compiler.WordTypes.commaSign) + ErrorMessage.sendErrorMessage (lineNumber, "Commas does not match in the parameter"); + + + int lastComma = -1; + for (int i = 0; i < logicOrder.Length; i++) { + if (logicOrder [i].currentType == Compiler.WordTypes.commaSign) { + + if (i == lastComma + 1) { + ErrorMessage.sendErrorMessage (lineNumber, "Stacked commas in parameter"); + return null; + } else { + + List tempList = new List (); + for (int j = lastComma + 1; j < i; j++) + tempList.Add (logicOrder [j]); + + packedLogic.Add (tempList); + lastComma = i; + } + + } + } + + // Fixes the last package should be written as a function for beautiful code later + List tempList2 = new List (); + for (int j = lastComma+1; j < logicOrder.Length; j++) + tempList2.Add (logicOrder [j]); + + packedLogic.Add (tempList2); + + + return packedLogic; + } + + + + + } + +} + diff --git a/LineParser/Parsers/InternalParseFunctions.cs b/LineParser/Parsers/InternalParseFunctions.cs new file mode 100644 index 0000000..625c6c5 --- /dev/null +++ b/LineParser/Parsers/InternalParseFunctions.cs @@ -0,0 +1,24 @@ +using System; +using ErrorHandler; + +namespace Compiler +{ + public class InternalParseFunctions + { + + public static Logic[] getSubArray(Logic[] logicOrder, int startIndex, int endIndex, int lineNumber){ + if (startIndex < logicOrder.Length && endIndex < logicOrder.Length) { + Logic[] subArray = new Logic[endIndex - startIndex + 1]; + for (int i = startIndex; i <= endIndex; i++) + subArray [i - startIndex] = logicOrder [i]; + + return subArray; + } else + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.corruptAndOrStatement.ToString(), null); + + return null; + } + + } +} + diff --git a/LineParser/Parsers/Lines/LineParser.cs b/LineParser/Parsers/Lines/LineParser.cs new file mode 100644 index 0000000..41c8756 --- /dev/null +++ b/LineParser/Parsers/Lines/LineParser.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + public class LineParser + { + public static List parseLines(List lineList){ + List tempList = new List (); + + for (int i = 0; i < lineList.Count; i++) { + if (lineList [i].theString != "" && containsChar(lineList[i].theString) && !isComment(lineList[i].theString)) { + int indentLevel = getIndentLevel (lineList [i].theString); + string trimmedString = lineList [i].theString.Substring (indentLevel, lineList [i].theString.Length - indentLevel); + string[] words = WordParser.parseWords (trimmedString); + addLine (tempList, lineList[i].lineNumber, indentLevel, words); + } + } + + return tempList; + } + + private static bool containsChar(string line){ + if (string.IsNullOrEmpty(line.Trim())) + return false; + return true; + } + + private static bool isComment(string line){ + for (int i = 0; i < line.Length; i++) + if (char.IsWhiteSpace (line [i]) == false) { + if (line [i] == '#') + return true; + + return false; + } + + return false; + } + + private static int getIndentLevel(string line){ + int indentCounter = 0; + for (int i = 0; i < line.Length; i++) { + if (line [i] == '\t') + indentCounter++; + else + break; + } + + return indentCounter; + } + + private static void addLine(List programCodeLines ,int lineNumber, int indentLevel, string[] words){ + CodeLine temp = new CodeLine (lineNumber, indentLevel, words); + programCodeLines.Add (temp); + } + } +} + diff --git a/LineParser/Parsers/Lines/LineSplitter.cs b/LineParser/Parsers/Lines/LineSplitter.cs new file mode 100644 index 0000000..8e1784d --- /dev/null +++ b/LineParser/Parsers/Lines/LineSplitter.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + internal class LineSplitter + { + public static List splitTextIntoLines(string currentText){ + List tempList = new List (); + + string tempLine = ""; + int currentLineNumber = 1; + int lastLinePos = -1; + + for (int i = 0; i < currentText.Length; i++) { + if (currentText [i] == '\n') { + tempLine = currentText.Substring (lastLinePos + 1, i - (lastLinePos + 1)); + tempList.Add (new ParsedLine(tempLine, currentLineNumber)); + lastLinePos = i; + currentLineNumber++; + } + } + + if (lastLinePos != currentText.Length) { + tempLine = currentText.Substring (lastLinePos + 1, currentText.Length - (lastLinePos + 1)); + tempList.Add (new ParsedLine(tempLine, currentLineNumber)); + } + + return tempList; + } + } +} + diff --git a/LineParser/Parsers/Lines/ParsedLine.cs b/LineParser/Parsers/Lines/ParsedLine.cs new file mode 100644 index 0000000..47bba2a --- /dev/null +++ b/LineParser/Parsers/Lines/ParsedLine.cs @@ -0,0 +1,16 @@ +using System; + +namespace Compiler +{ + public class ParsedLine{ + public string theString; + public int lineNumber; + + public ParsedLine(string text, int lineNumber){ + this.theString = text; + this.lineNumber = lineNumber; + } + + } +} + diff --git a/LineParser/Parsers/Logics/PostLogicParsing.cs b/LineParser/Parsers/Logics/PostLogicParsing.cs new file mode 100644 index 0000000..60fe62e --- /dev/null +++ b/LineParser/Parsers/Logics/PostLogicParsing.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Runtime; + +namespace Compiler +{ + public class PostLogicParsing + { + + /// + /// Split Packages and Statements. Combine Variables and Packages into FunctionCalls. + /// + public static Logic[] parsePostLogics(Logic[] logicOrder, int lineNumber, Scope currentScope){ + logicOrder = splitPackagesAndStatements(logicOrder, lineNumber, currentScope); + return parseVariablesAndPackagesIntoFunctionCalls (logicOrder, lineNumber, currentScope); + } + + + private static Logic[] splitPackagesAndStatements(Logic[] logicOrder, int lineNumber, Scope currentScope){ + List newOrder = new List (); + + for (int i = 0; i < logicOrder.Length; i++) { + if (logicOrder [i].currentType == WordTypes.functionCall && SpecialWordParser.isKeyWord ((logicOrder [i] as FunctionCall).name)) { + + Package temp = new Package ("(" + (logicOrder [i] as FunctionCall).parameter + ")", lineNumber); + temp.logicOrder = WordsToLogicParser.determineLogicFromWords (new string[]{ temp.word}, lineNumber, currentScope); + + if ((logicOrder [i] as FunctionCall).name == "if") { + newOrder.Add (new IfStatement ()); + newOrder.Add(temp); + } + else if ((logicOrder [i] as FunctionCall).name == "while") { + newOrder.Add (new WhileLoop ()); + newOrder.Add(temp); + } + + } else + newOrder.Add (logicOrder [i]); + } + return newOrder.ToArray(); + } + + + private static Logic[] parseVariablesAndPackagesIntoFunctionCalls(Logic[] logicOrder, int lineNumber, Scope currentScope){ + List tempOrder = new List (); + + for (int i = 0; i < logicOrder.Length; i++) + if (logicOrder [i].currentType == WordTypes.variable && (i+1 < logicOrder.Length && logicOrder[i+1].currentType == WordTypes.package)) { + Logic theFuncCall = FunctionParser.parseIntoFunctionCall (logicOrder [i].word + logicOrder [i + 1].word, lineNumber, currentScope); + tempOrder.Add (theFuncCall); + i += 1; + } + else + tempOrder.Add (logicOrder [i]); + + return tempOrder.ToArray (); + } + + } +} + diff --git a/LineParser/Parsers/Logics/WordsToLogicParser.cs b/LineParser/Parsers/Logics/WordsToLogicParser.cs new file mode 100644 index 0000000..2ff6916 --- /dev/null +++ b/LineParser/Parsers/Logics/WordsToLogicParser.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + public class WordsToLogicParser{ + + + public static Logic[] determineLogicFromWords(string[] words, int lineNumber, Scope currentScope){ + Logic[] logicOrder = new Logic[words.Length]; + + for (int i = 0; i < words.Length; i++) { + logicOrder [i] = getCurrentLogic (words [i], lineNumber, currentScope); + if (logicOrder [i].currentType == WordTypes.package) { + PackageUnWrapper.unpackPackage (words [i], lineNumber, currentScope, logicOrder [i] as Package); + } + } + + logicOrder = PostLogicParsing.parsePostLogics (logicOrder, lineNumber, currentScope); + + return logicOrder; + } + + + + private static Logic getCurrentLogic(string word, int lineNumber, Scope currentScope){ + + if (word == ",") + return new CommaSign(); + + if (word == ">") + return new GreaterThenSign(); + + if (word == "<") + return new LessThenSign(); + + if (word == ":") + return new IndentOperator(); + + if (word == "!") + return new XorOperator (word); + + if (word == "not") + return new NotOperator (word); + + if (word == "or") + return new OrOperator (word); + + if (word == "and") + return new AndOperator (word); + + + if (isBooleanValue (word) == 1) + return new BooleanValue (true); + if (isBooleanValue (word) == 0) + return new BooleanValue (false); + + + if (isNumber (word)) + return new NumberValue(word); + + if (isString (word)) + return new TextValue (word); + + + if (SpecialWordParser.isKeyWord (word)) { + SpecialWordParser.checkIfUnsupportedKeyword (word, lineNumber); + WordTypes specialType = SpecialWordParser.getSpecialType (word, lineNumber); + + if (specialType == WordTypes.forLoop) + return new ForLoop (); + + if (specialType == WordTypes.whileLoop) + return new WhileLoop (); + + if (specialType == WordTypes.ifOperator) + return new IfStatement (); + + if (specialType == WordTypes.elifOperator) + return new ElifStatement (); + + if (specialType == WordTypes.elseOperator) + return new ElseStatement (); + + if (specialType == WordTypes.defStatement) + return new DefStatement (); + + if (specialType == WordTypes.returnStatement) + return new ReturnStatement (); + + if (specialType == WordTypes.breakStatement) + return new BreakStatement (); + + if (specialType == WordTypes.continueStatement) + return new ContinueStatment (); + } + + + + if (startsWithDigitOrWeirdChar(word) == false) { + + if (endsWithParantes (word)) { + Logic temp = FunctionParser.parseIntoFunctionCall (word, lineNumber, currentScope); + if (temp != null) + return temp; + } + else { + if(containsButNotStartWithDigitWeirdChar(word) == false) + return checkVariable(word, currentScope.scopeVariables); + } + + + } + + if (word.Length == 1) { + if (word [0] == '=') + return new EqualSign (); + if(isMathOperator(word[0])) + return new MathOperator(word); + } + + if (isPackage (word)) { + + return new Package(word, lineNumber); + } + + return new UnknownLogic (lineNumber); + } + + + private static Logic checkVariable(string word, Variables scopeVariables){ + + int variablePos = scopeVariables.containsVariable (word); + if (variablePos >= 0) { + return scopeVariables.variableList [variablePos]; + } + + return new Variable (word); + } + + + + private static int isBooleanValue(string word){ + if (word == "True") + return 1; + if (word == "False") + return 0; + + return -1; + } + + + private static bool isNumber(string word){ + double testNumber = 0; + + return double.TryParse (word, out testNumber); + } + + private static bool isMathOperator(char c){ + for(int i = 0; i < MathParser.mathOperators.Length; i++) + if(c == MathParser.mathOperators[i]) + return true; + + return false; + } + + + private static bool startsWithDigitOrWeirdChar(string word){ + if(char.IsLetter(word[0])) + return false; + + if (word [0] == '_') + return false; + + return true; + } + + private static bool containsButNotStartWithDigitWeirdChar(string word){ + if (word.Length == 1) + return false; + + for (int i = 1; i < word.Length; i++) + if (!char.IsLetter (word [i]) && !char.IsDigit (word [i]) && word [i] != '_') + return true; + + return false; + } + + private static bool endsWithParantes(string word){ + if(word[word.Length-1] == ')') + return true; + + return false; + } + + + private static bool isPackage(string word){ + if (word [0] == '(' && word [word.Length - 1] == ')') + return true; + + return false; + } + + private static bool isString(string word){ + if (word [0] == '"' && word [word.Length - 1] == '"') + return true; + + return false; + } + + } + +} + diff --git a/LineParser/Parsers/SpecialWordParser.cs b/LineParser/Parsers/SpecialWordParser.cs new file mode 100644 index 0000000..ba00a21 --- /dev/null +++ b/LineParser/Parsers/SpecialWordParser.cs @@ -0,0 +1,121 @@ +using System; +using Runtime; +using ErrorHandler; + +namespace Compiler +{ + + public class SpecialWordParser{ + + public static readonly string[] keywords = {"while", "for", "in", "if", "else", "elif", "def", "return", "break", "continue"}; + public static readonly string[] scopeStarters = {"while", "for", "if", "else", "elif", "def"}; + + public static readonly string[] unSupportedKeywords = {"as", "assert", "class", "del", "except", + "exec", "finally", "from", "global", "import", "is", "lambda", "pass", "raise", "try", "with", "yield", "None"}; + + + public static Logic parseSpecialLine(Logic[] logicOrder, int lineNumber, Scope currentScope){ + + switch (logicOrder[0].currentType) { + + case WordTypes.elifOperator: + case WordTypes.ifOperator: + return IfAndElifStatementParser.parseStatement (logicOrder, lineNumber, currentScope); + + case WordTypes.elseOperator: + return ElseStatementParser.parseElseStatement (logicOrder, lineNumber, currentScope); + + case WordTypes.forLoop: + return ForLoopParser.parseForLoop(logicOrder, lineNumber, currentScope); + + case WordTypes.whileLoop: + return WhileLoopParser.parseWhileLoop(logicOrder, lineNumber, currentScope); + + case WordTypes.defStatement: + return DefStatementParser.parseDefStatement(logicOrder, lineNumber, currentScope); + + case WordTypes.returnStatement: + return ReturnStatementParser.parseReturnStatement (logicOrder, lineNumber, currentScope); + + case WordTypes.breakStatement: + return BreakAndContinueStatementParser.parseBreakStatement (logicOrder, lineNumber, currentScope); + + case WordTypes.continueStatement: + return BreakAndContinueStatementParser.parseContinueStatement (logicOrder, lineNumber, currentScope); + + + default: + return new UnknownLogic(lineNumber); + } + } + + + public static bool isKeyWord(string word){ + foreach (string s in keywords) + if (s == word) + return true; + + foreach (string s in unSupportedKeywords) + if (s == word) + return true; + + return false; + } + + public static void checkIfUnsupportedKeyword(string word,int lineNumber){ + foreach (string s in unSupportedKeywords) + if (s == word) + ErrorMessage.sendErrorMessage (lineNumber, s + " stöds inte i detta spel"); + } + + public static WordTypes getSpecialType(string word, int lineNumber){ + + if (word == "while") + return WordTypes.whileLoop; + + if (word == "for") + return WordTypes.forLoop; + + if (word == "if") + return WordTypes.ifOperator; + + if (word == "else") + return WordTypes.elseOperator; + + if (word == "elif") + return WordTypes.elifOperator; + + if (word == "in") + return WordTypes.inWord; + + if (word == "def") + return WordTypes.defStatement; + + if (word == "return") + return WordTypes.returnStatement; + + if (word == "break") + return WordTypes.breakStatement; + + if (word == "continue") + return WordTypes.continueStatement; + + ErrorMessage.sendErrorMessage (lineNumber, word + " antogs vara ett keyword, men något gick fel"); + return WordTypes.unknown; + } + + + public static bool isValidScopeStarter(Logic[] logicOrder, int lineNumber){ + + if (logicOrder[0] is ScopeStarter){ + return true; + } + + + return false; + } + + } + +} + diff --git a/LineParser/Parsers/Statements/DefStatementParser.cs b/LineParser/Parsers/Statements/DefStatementParser.cs new file mode 100644 index 0000000..e8b86b8 --- /dev/null +++ b/LineParser/Parsers/Statements/DefStatementParser.cs @@ -0,0 +1,32 @@ +using ErrorHandler; +using System.Collections; +using System.Collections.Generic; +using Runtime; + +namespace Compiler { + + public class DefStatementParser{ + + + // Could be optimized so that we save left, right and operators for next comparision so we do not need to parse every loop instance! + + + public static Logic parseDefStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + FunctionCall theFuncCall = logicOrder [1] as FunctionCall; + + if(SpecialWordParser.isKeyWord(theFuncCall.name)) + ErrorMessage.sendErrorMessage (lineNumber,string.Format( "\"{0}\" är ett Python keyword, du kan därför inte döpa en funktion till det", theFuncCall.name)); + + int paraAmount = (FunctionParser.getParameterAmount (theFuncCall.parameter, lineNumber, currentScope)); + UserFunction theFunc = new UserFunction (theFuncCall.name, (logicOrder [0] as ScopeStarter).getTargetScope(), paraAmount); + currentScope.scopeFunctions.addFunction(theFunc); + + theFunc.inputParameterNames = FunctionParser.getParameterNames (theFuncCall.parameter, lineNumber, currentScope); + + return new DefStatement (); + } + + + } + +} \ No newline at end of file diff --git a/LineParser/Parsers/Statements/ElseStatementParser.cs b/LineParser/Parsers/Statements/ElseStatementParser.cs new file mode 100644 index 0000000..64ead8f --- /dev/null +++ b/LineParser/Parsers/Statements/ElseStatementParser.cs @@ -0,0 +1,22 @@ +using ErrorHandler; +using System.Collections; + +namespace Compiler { + + public class ElseStatementParser{ + + + public static Logic parseElseStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + + if (logicOrder [logicOrder.Length - 1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ElseStatements, ElseErrorType.missingIndentOperator.ToString(), null); + + if (logicOrder.Length != 2) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ElseStatements, ElseErrorType.unknownFormat.ToString(), null); + + + return (logicOrder[0] as ElseStatement); + } + + } +} \ No newline at end of file diff --git a/LineParser/Parsers/Statements/ForLoopParser.cs b/LineParser/Parsers/Statements/ForLoopParser.cs new file mode 100644 index 0000000..5cf380c --- /dev/null +++ b/LineParser/Parsers/Statements/ForLoopParser.cs @@ -0,0 +1,86 @@ +using ErrorHandler; +using System.Collections; +using Runtime; + +namespace Compiler { + + public class ForLoopParser{ + + public static Logic parseForLoop(Logic[] logicOrder, int lineNumber, Scope currentScope){ + syntaxCheckForLoop (logicOrder, lineNumber); + + + #region get & check variables + FunctionCall rangeCall = (logicOrder [3] as FunctionCall); + Variable[] inputVariables = FunctionParser.getValueOfParameters (rangeCall.parameter, rangeCall.targetFunc, lineNumber, currentScope, rangeCall); + + // Checks if inputVariables is empty and else if only numbers + if (inputVariables.Length == 0) { + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.rangeArgumentEmpty.ToString(), null); + } + else { + foreach (Variable v in inputVariables) + if(v.variableType != VariableTypes.number) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.rangeArgumentNotNumber.ToString(), null); + } + #endregion + + + ForLoop returnLoop = new ForLoop (); + returnLoop.setTargetScope((logicOrder [0] as ScopeStarter).getTargetScope()); + returnLoop.getTargetScope().theScoopLoop = returnLoop; + + string counterName = logicOrder[1].word; + if (inputVariables.Length == 1) + returnLoop.setLoopVariables(counterName, 0,inputVariables [0].getNumber (), 1); + + if (inputVariables.Length == 2) + returnLoop.setLoopVariables(counterName, inputVariables [0].getNumber (), inputVariables [1].getNumber (), 1); + + if (inputVariables.Length == 3) + returnLoop.setLoopVariables(counterName, inputVariables [0].getNumber (), inputVariables [1].getNumber (), inputVariables [2].getNumber ()); + + returnLoop.doEnterScope = returnLoop.makeComparison (lineNumber, false); + returnLoop.addCounterVariableToScope(lineNumber); + + + return returnLoop; + } + + + + private static void syntaxCheckForLoop(Logic[] logicOrder, int lineNumber){ + + if (logicOrder.Length == 4) { + checkCorrectWordsForLoop (logicOrder, lineNumber); + } else if (logicOrder.Length < 4 || logicOrder.Length > 5) { + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.unknownFormat.ToString(), null); + } else { + checkCorrectWordsForLoop (logicOrder, lineNumber); + } + } + + private static void checkCorrectWordsForLoop (Logic[] logicOrder, int lineNumber){ + + if (logicOrder [logicOrder.Length - 1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.missingIndentOperator.ToString(), null); + + if (logicOrder [1].currentType != WordTypes.variable || logicOrder [1].word == "in") + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.expectVariableAt2.ToString(), null); + + if (logicOrder [2].word != "in") + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.expectInAt3.ToString(), null); + + if (logicOrder [3].currentType != WordTypes.functionCall) { + if (logicOrder [3].currentType == WordTypes.variable && logicOrder[3].word == "range") + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.rangeMissingParenthesis.ToString(), null); + else + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.expectRangeAt4.ToString(), null); + } + + if ((logicOrder [3] as FunctionCall).name != "range") + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ForLoop, ForLoopErrorType.expectRangeAt4.ToString(), null); + } + } + +} \ No newline at end of file diff --git a/LineParser/Parsers/Statements/IfAndElifStatementParser.cs b/LineParser/Parsers/Statements/IfAndElifStatementParser.cs new file mode 100644 index 0000000..1409d65 --- /dev/null +++ b/LineParser/Parsers/Statements/IfAndElifStatementParser.cs @@ -0,0 +1,28 @@ +using ErrorHandler; +using System.Collections; +using Runtime; + +namespace Compiler { + public class IfAndElifStatementParser{ + + public static Logic parseStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + if (logicOrder.Length < 3) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.IfStatements, IfErrorType.unknownFormat.ToString(), null); + + if (logicOrder [logicOrder.Length - 1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.IfStatements, IfErrorType.missingIndentOperator.ToString(), null); + + + Logic[] statementLogic = InternalParseFunctions.getSubArray (logicOrder, 1, logicOrder.Length - 2, lineNumber); + (logicOrder [0] as ScopeStarter).doEnterScope = StatementParser.parseAndCheckStatement (statementLogic, lineNumber, currentScope); + (logicOrder [0] as ComparisonScope).initNextstatement (); + + if(logicOrder[0] is IfStatement) + return (logicOrder[0] as IfStatement); + + return (logicOrder[0] as ElifStatement); + } + + } + +} \ No newline at end of file diff --git a/LineParser/Parsers/Statements/ReturnStatementParser.cs b/LineParser/Parsers/Statements/ReturnStatementParser.cs new file mode 100644 index 0000000..240ef0f --- /dev/null +++ b/LineParser/Parsers/Statements/ReturnStatementParser.cs @@ -0,0 +1,47 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class ReturnStatementParser + { + public static Logic parseReturnStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + if (logicOrder.Length <= 1) { + } + + Variable returnSum; + + if (logicOrder.Length <= 1) { + // Should return None if there is no sum to return + returnSum = new Variable (); + + //This error should not exist + ErrorMessage.sendErrorMessage (lineNumber, "I detta moment måste du returnera något ur funktionen"); + } + else { + Logic[] followOrder = InternalParseFunctions.getSubArray (logicOrder, 1, logicOrder.Length - 1, lineNumber); + returnSum = SumParser.parseIntoSum (followOrder, lineNumber, currentScope); + } + + ReturnStatement theReturn = (logicOrder [0] as ReturnStatement); + theReturn.findFunctionParent (currentScope, lineNumber); + + CodeLine parentLine = theReturn.FunctionParent.parentScope.codeLines [theReturn.FunctionParent.parentScope.lastReadLine]; + ReturnMemoryControll.insertReturnValue (parentLine, lineNumber, returnSum); + + + currentScope.isReturning = true; + CodeWalker.setReturnTarget (theReturn.FunctionParent.parentScope); + + return (logicOrder [0] as ReturnStatement); + } + + } + + + + + +} + diff --git a/LineParser/Parsers/Statements/WhileLoopParser.cs b/LineParser/Parsers/Statements/WhileLoopParser.cs new file mode 100644 index 0000000..f086e7a --- /dev/null +++ b/LineParser/Parsers/Statements/WhileLoopParser.cs @@ -0,0 +1,40 @@ +using ErrorHandler; +using System.Collections; +using System.Collections.Generic; + +namespace Compiler { + + public class WhileLoopParser{ + + + // Could be optimized so that we save left, right and operators for next comparision so we do not need to parse every loop instance! + + + public static Logic parseWhileLoop(Logic[] logicOrder, int lineNumber, Scope currentScope){ + if (logicOrder.Length < 3) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.WhileLoop, WhileErrorType.unknownFormat.ToString(), null); + + if (logicOrder [logicOrder.Length -1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.WhileLoop, WhileErrorType.missingIndentOperator.ToString(), null); + + Logic[] statementLogic = new Logic[logicOrder.Length - 2]; + for (int i = 1; i < logicOrder.Length - 1; i++) + statementLogic [i - 1] = logicOrder [i]; + + + WhileLoop returnLoop = new WhileLoop (); + returnLoop.setTargetScope((logicOrder [0] as ScopeStarter).getTargetScope()); + returnLoop.getTargetScope().theScoopLoop = returnLoop; + + + returnLoop.doEnterScope = StatementParser.parseAndCheckStatement (statementLogic, lineNumber, currentScope); + returnLoop.theStatement = statementLogic; + + + return returnLoop; + } + + + } + +} \ No newline at end of file diff --git a/LineParser/Parsers/SumParser/BooleanAlgebra/BoolAlgebraParser.cs b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolAlgebraParser.cs new file mode 100644 index 0000000..4fe2510 --- /dev/null +++ b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolAlgebraParser.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using ErrorHandler; +using B83; +using Runtime; + +namespace Compiler +{ + public class BoolAlgebraParser + { + public static bool parseBoolAlgebraStatement(BoolAlgebraWord[] logicOrder, int lineNumber){ + string calcString = ""; + foreach (BoolAlgebraWord w in logicOrder) + calcString += w.calcWord; + + int sum = (int)SyntaxCheck.globalParser.Evaluate (calcString); + + return Convert.ToBoolean(sum); + } + + + + + public static BoolAlgebraWord[] parseIntoBoolAlgebra(Logic[] logicOrder, int lineNumber, Scope currentScope){ + List algebraList = new List (); + + int lastOperatorPos = -1; + for (int i = 0; i < logicOrder.Length; i++) + if (logicOrder [i] is AndOrOperator) { + + Logic[] partStatement = InternalParseFunctions.getSubArray (logicOrder, lastOperatorPos + 1, i-1, lineNumber); + + bool tempResult = StatementParser.parseExpression (partStatement, lineNumber, currentScope); + algebraList.Add (new BoolAlgebraWord (tempResult.ToString ())); + algebraList.Add (new BoolAlgebraWord (logicOrder [i].word)); + + lastOperatorPos = i; + } + + + Logic[] finalStatement = InternalParseFunctions.getSubArray (logicOrder, lastOperatorPos + 1, logicOrder.Length-1, lineNumber); + bool finalResult = StatementParser.parseExpression (finalStatement, lineNumber, currentScope); + algebraList.Add (new BoolAlgebraWord (finalResult.ToString ())); + + return algebraList.ToArray (); + } + + } + +} + diff --git a/LineParser/Parsers/SumParser/BooleanAlgebra/BoolAlgebraWord.cs b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolAlgebraWord.cs new file mode 100644 index 0000000..b888c4c --- /dev/null +++ b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolAlgebraWord.cs @@ -0,0 +1,29 @@ +using System; + +namespace Compiler +{ + public class BoolAlgebraWord + { + public string calcWord; + + public BoolAlgebraWord (string word) + { + if (word == "and" || word == "or") + setOperatorSettings (word); + else + setValueSettings (word); + } + + private void setOperatorSettings(string word){ + if (word == "and") + calcWord = "*"; + else + calcWord = "+"; + } + + private void setValueSettings(string word){ + calcWord = Convert.ToInt32 (Convert.ToBoolean (word)).ToString(); + } + } +} + diff --git a/LineParser/Parsers/SumParser/BooleanAlgebra/BoolExpressionParser.cs b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolExpressionParser.cs new file mode 100644 index 0000000..12bf184 --- /dev/null +++ b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolExpressionParser.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using Runtime; +using ErrorHandler; +using System.Linq; + +namespace Compiler +{ + public class BoolExpressionParser + { + + + public static Logic[] compressAndOrStatements(Logic[] preLogicOrder, int lineNumber, Scope currentScope){ + bool foundAndOr = BoolCompressExpressions.hasAndOr(preLogicOrder, lineNumber); + + if (foundAndOr) { + string boolString = convertIntoBoolAlgebra (preLogicOrder, lineNumber, currentScope); + if (SyntaxCheck.globalParser.Evaluate (boolString) != 0) + return new Logic[1]{ new BooleanValue (true) }; + + return new Logic[1]{ new BooleanValue (false) }; + } + else + return (preLogicOrder [0] as Package).logicOrder; + } + + + private static string convertIntoBoolAlgebra(Logic[] logicOrder, int lineNumber, Scope currentScope){ + string boolString = ""; + for (int i = 0; i < logicOrder.Length; i++) { + if (logicOrder [i] is AndOrOperator) { + if(logicOrder[i].currentType == WordTypes.andOperator) + boolString += "*"; + else + boolString += "+"; + + continue; + } + + if (logicOrder [i].currentType == WordTypes.package) { + Variable tempSum = SumParser.parseIntoSum ((logicOrder [i] as Package).logicOrder, lineNumber, currentScope); + if (tempSum.getBool ()) + boolString += "1"; + else + boolString += "0"; + } + else + ErrorMessage.sendErrorMessage (lineNumber, "Korrupt uttryck"); + } + + return boolString; + } + + + } +} + diff --git a/LineParser/Parsers/SumParser/BooleanAlgebra/BoolExpressions/BoolCompressExpressions.cs b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolExpressions/BoolCompressExpressions.cs new file mode 100644 index 0000000..3117c0a --- /dev/null +++ b/LineParser/Parsers/SumParser/BooleanAlgebra/BoolExpressions/BoolCompressExpressions.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using ErrorHandler; +using Runtime; + + +namespace Compiler +{ + public class BoolCompressExpressions + { + + public static Logic[] compressExpression(Logic[] preLogicOrder, int lineNumber, Scope currentScope, bool solveExpressions){ + Logic[] logicOrder = splitAtAndOr ((Logic[])preLogicOrder.Clone (), lineNumber); + + foreach (Logic l in logicOrder) + if (l is Package && hasValidComparison ((l as Package).logicOrder, lineNumber)) + (l as Package).logicOrder = new Logic[1]{ new BooleanExpression ((l as Package).logicOrder, lineNumber, currentScope) }; + + + return logicOrder; + } + + + private static bool hasValidComparison(Logic[] logicOrder, int lineNumber){ + int foundCounter = 0; + bool foundComparison = false; + + for (int i = 0; i < logicOrder.Length; i++) { + if (logicOrder [i] is ComparisonOperator) + foundCounter++; + else + foundCounter = 0; + + if (foundCounter > 0) { + foundComparison = true; + if (foundCounter > 2) + ErrorMessage.sendErrorMessage (lineNumber, "Kombinationen: " + logicOrder [i - 2].word + logicOrder [i - 1].word + logicOrder [i].word + " är inte tillåten"); + } + } + if (logicOrder [0] is ComparisonOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Ett boolskt utryck kan inte börja med en jämförelseoperator"); + if (logicOrder [logicOrder.Length-1] is ComparisonOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Ett boolskt utryck kan inte sluta med en jämförelseoperator"); + + return foundComparison; + } + + + public static bool hasAndOr(Logic[] logicOrder, int lineNumber){ + foreach (Logic l in logicOrder) + if (l is AndOrOperator) + return true; + return false; + } + + private static Logic[] splitAtAndOr(Logic[] logicOrder, int lineNumber){ + if(hasAndOr(logicOrder, lineNumber) == false) + return new Logic[1]{ new Package(logicOrder, lineNumber)}; + + List compressedOrder = new List (); + int lastFound = 0; + + for(int i = 0; i < logicOrder.Length; i++){ + if (logicOrder [i] is AndOrOperator) { + if (i == 0 || i == logicOrder.Length - 1) + ErrorMessage.sendErrorMessage (lineNumber, "Kan inte börja eller sluta med And/Or"); + + Logic[] subArray = InternalParseFunctions.getSubArray (logicOrder, lastFound, i - 1, lineNumber); + compressedOrder.Add (new Package (subArray, lineNumber)); + + if (logicOrder [i + 1] is AndOrOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Kan inte ha 2 And/Or direkt efter varandra"); + + lastFound = i + 1; + compressedOrder.Add (logicOrder [i]); + } + } + Logic[] endArray = InternalParseFunctions.getSubArray (logicOrder, lastFound, logicOrder.Length-1, lineNumber); + compressedOrder.Add (new Package (endArray, lineNumber)); + + + return compressedOrder.ToArray (); + } + + } +} + diff --git a/LineParser/Parsers/SumParser/BooleanAlgebra/BooleanExpression.cs b/LineParser/Parsers/SumParser/BooleanAlgebra/BooleanExpression.cs new file mode 100644 index 0000000..822fffb --- /dev/null +++ b/LineParser/Parsers/SumParser/BooleanAlgebra/BooleanExpression.cs @@ -0,0 +1,25 @@ +using System; +using Runtime; + +namespace Compiler +{ + public class BooleanExpression : Logic, BoolType + { + private Logic[] logicOrder; + private int lineNumber; + private Scope currentScope; + + public BooleanExpression (Logic[] logicOrder, int lineNumber, Scope currentScope) + { + base.currentType = WordTypes.booleanExpression; + this.logicOrder = logicOrder; + this.lineNumber = lineNumber; + this.currentScope = currentScope; + } + + public BooleanValue parseExpression(){ + return new BooleanValue(StatementParser.parseStatement(logicOrder, lineNumber, currentScope)); + } + } +} + diff --git a/LineParser/Parsers/SumParser/BooleanAlgebra/BooleanSumParser.cs b/LineParser/Parsers/SumParser/BooleanAlgebra/BooleanSumParser.cs new file mode 100644 index 0000000..91dbf38 --- /dev/null +++ b/LineParser/Parsers/SumParser/BooleanAlgebra/BooleanSumParser.cs @@ -0,0 +1,49 @@ +using System.Collections; +using Runtime; + +namespace Compiler{ + + internal class BooleanSumParser{ + + public static Variable validBoolSum(Logic[] logicOrder, int lineNumber){ + #region parse out the not operators + int notNotIndex = 0; + int notCounter = 0; + for (int i = 0; i < logicOrder.Length; i++) + if (logicOrder [i].currentType == WordTypes.notOperator) + notCounter++; + else { + notNotIndex = i; + break; + } + + if (logicOrder.Length - notNotIndex != 1) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Korrupt Sant eller Falskt värde"); + #endregion + + + if (logicOrder [notNotIndex].currentType == WordTypes.variable) { + if (notCounter % 2 == 0) + return new Variable("BoolVar", (logicOrder [notNotIndex] as Variable).getBool(), true); + else + return new Variable("BoolVar", !(logicOrder [notNotIndex] as Variable).getBool(), true); + } + + if (logicOrder [notNotIndex].currentType == WordTypes.booleanValue) { + if (notCounter % 2 == 0) + return new Variable("BoolVar", (logicOrder [notNotIndex] as BooleanValue).value, true); + else + return new Variable("BoolVar", !(logicOrder [notNotIndex] as BooleanValue).value, true); + } + + if (logicOrder [notNotIndex].currentType == WordTypes.booleanExpression) + return new Variable ("Possible Bool Sum", false, true); + + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Något gick fel med Sant eller Falsk parsing"); + return new Variable (); + } + + } + + +} \ No newline at end of file diff --git a/LineParser/Parsers/SumParser/Exceptions/FunctionCallException.cs b/LineParser/Parsers/SumParser/Exceptions/FunctionCallException.cs new file mode 100644 index 0000000..1fc6670 --- /dev/null +++ b/LineParser/Parsers/SumParser/Exceptions/FunctionCallException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Compiler +{ + public class FunctionCallException : Exception + { + } +} + diff --git a/LineParser/Parsers/SumParser/ExpressionParser.cs b/LineParser/Parsers/SumParser/ExpressionParser.cs new file mode 100644 index 0000000..7e95269 --- /dev/null +++ b/LineParser/Parsers/SumParser/ExpressionParser.cs @@ -0,0 +1,576 @@ +/* * * * * * * * * * * * * * + * A simple expression parser + * -------------------------- + * + * The parser can parse a mathematical expression into a simple custom + * expression tree. It can recognise methods and fields/contants which + * are user extensible. It can also contain expression parameters which + * are registrated automatically. An expression tree can be "converted" + * into a delegate. + * + * Written by Bunny83 + * 2014-11-02 + * + * Features: + * - Elementary arithmetic [ + - * / ] +* - Power [ ^ ] +* - Brackets ( ) +* - Most function from System.Math (abs, sin, round, floor, min, ...) +* - Constants ( e, PI ) +* - MultiValue return (quite slow, produce extra garbage each call) + * + * * * * * * * * * * * * * */ + + + using System.Linq; +using System.Collections.Generic; + using Runtime; +using System; + +namespace B83.ExpressionParser +{ + public interface IValue + { + double Value { get; } + } + public class Number : IValue + { + private double m_Value; + public double Value + { + get { return m_Value; } + set { m_Value = value; } + } + public Number(double aValue) + { + m_Value = aValue; + } + public override string ToString() + { + return "" + m_Value + ""; + } + } + public class OperationSum : IValue + { + private IValue[] m_Values; + public double Value + { + get { return m_Values.Select(v => v.Value).Sum(); } + } + public OperationSum(params IValue[] aValues) + { + // collapse unnecessary nested sum operations. + List v = new List(aValues.Length); + foreach (var I in aValues) + { + var sum = I as OperationSum; + if (sum == null) + v.Add(I); + else + v.AddRange(sum.m_Values); + } + m_Values = v.ToArray(); + } + public override string ToString() + { + return "( " + string.Join(" + ", m_Values.Select(v => v.ToString()).ToArray()) + " )"; + } + } + public class OperationProduct : IValue + { + private IValue[] m_Values; + public double Value + { + get { return m_Values.Select(v => v.Value).Aggregate((v1, v2) => v1 * v2); } + } + public OperationProduct(params IValue[] aValues) + { + m_Values = aValues; + } + public override string ToString() + { + return "( " + string.Join(" * ", m_Values.Select(v => v.ToString()).ToArray()) + " )"; + } + + } + public class OperationPower : IValue + { + private IValue m_Value; + private IValue m_Power; + public double Value + { + get { return System.Math.Pow(m_Value.Value, m_Power.Value); } + } + public OperationPower(IValue aValue, IValue aPower) + { + m_Value = aValue; + m_Power = aPower; + } + public override string ToString() + { + return "( " + m_Value + "^" + m_Power + " )"; + } + + } + public class OperationNegate : IValue + { + private IValue m_Value; + public double Value + { + get { return -m_Value.Value; } + } + public OperationNegate(IValue aValue) + { + m_Value = aValue; + } + public override string ToString() + { + return "( -" + m_Value + " )"; + } + + } + public class OperationReciprocal : IValue + { + private IValue m_Value; + public double Value + { + get { return 1.0 / m_Value.Value; } + } + public OperationReciprocal(IValue aValue) + { + m_Value = aValue; + } + public override string ToString() + { + return "( 1/" + m_Value + " )"; + } + + } + + public class MultiParameterList : IValue + { + private IValue[] m_Values; + public IValue[] Parameters { get { return m_Values; } } + public double Value + { + get { return m_Values.Select(v => v.Value).FirstOrDefault(); } + } + public MultiParameterList(params IValue[] aValues) + { + m_Values = aValues; + } + public override string ToString() + { + return string.Join(", ", m_Values.Select(v => v.ToString()).ToArray()); + } + } + + public class CustomFunction : IValue + { + private IValue[] m_Params; + private System.Func m_Delegate; + private string m_Name; + public double Value + { + get + { + if (m_Params == null) + return m_Delegate(null); + return m_Delegate(m_Params.Select(p => p.Value).ToArray()); + } + } + public CustomFunction(string aName, System.Func aDelegate, params IValue[] aValues) + { + m_Delegate = aDelegate; + m_Params = aValues; + m_Name = aName; + } + public override string ToString() + { + if (m_Params == null) + return m_Name; + return m_Name + "( " + string.Join(", ", m_Params.Select(v => v.ToString()).ToArray()) + " )"; + } + } + public class Parameter : Number + { + public string Name { get; private set; } + public override string ToString() + { + return Name+"["+base.ToString()+"]"; + } + public Parameter(string aName) : base(0) + { + Name = aName; + } + } + + public class Expression : IValue + { + public Dictionary Parameters = new Dictionary(); + public IValue ExpressionTree { get; set; } + public double Value + { + get { return ExpressionTree.Value; } + } + public double[] MultiValue + { + get { + var t = ExpressionTree as MultiParameterList; + if (t != null) + { + double[] res = new double[t.Parameters.Length]; + for (int i = 0; i < res.Length; i++) + res[i] = t.Parameters[i].Value; + return res; + } + return null; + } + } + public override string ToString() + { + return ExpressionTree.ToString(); + } + public ExpressionDelegate ToDelegate(params string[] aParamOrder) + { + var parameters = new List(aParamOrder.Length); + for(int i = 0; i < aParamOrder.Length; i++) + { + if (Parameters.ContainsKey(aParamOrder[i])) + parameters.Add(Parameters[aParamOrder[i]]); + else + parameters.Add(null); + } + var parameters2 = parameters.ToArray(); + + return (p) => Invoke(p, parameters2); + } + public MultiResultDelegate ToMultiResultDelegate(params string[] aParamOrder) + { + var parameters = new List(aParamOrder.Length); + for (int i = 0; i < aParamOrder.Length; i++) + { + if (Parameters.ContainsKey(aParamOrder[i])) + parameters.Add(Parameters[aParamOrder[i]]); + else + parameters.Add(null); + } + var parameters2 = parameters.ToArray(); + + + return (p) => InvokeMultiResult(p, parameters2); + } + double Invoke(double[] aParams, Parameter[] aParamList) + { + int count = System.Math.Min(aParamList.Length, aParams.Length); + for (int i = 0; i < count; i++ ) + { + if (aParamList[i] != null) + aParamList[i].Value = aParams[i]; + } + return Value; + } + double[] InvokeMultiResult(double[] aParams, Parameter[] aParamList) + { + int count = System.Math.Min(aParamList.Length, aParams.Length); + for (int i = 0; i < count; i++) + { + if (aParamList[i] != null) + aParamList[i].Value = aParams[i]; + } + return MultiValue; + } + public static Expression Parse(string aExpression) + { + return new ExpressionParser().EvaluateExpression(aExpression); + } + + public class ParameterException : System.Exception { public ParameterException(string aMessage) : base(aMessage) { } } + } + public delegate double ExpressionDelegate(params double[] aParams); + public delegate double[] MultiResultDelegate(params double[] aParams); + + + + public class ExpressionParser + { + private List m_BracketHeap = new List(); + private Dictionary> m_Consts = new Dictionary>(); + private Dictionary> m_Funcs = new Dictionary>(); + private Expression m_Context; + + public ExpressionParser() + { + var rnd = new System.Random(); + m_Consts.Add("PI", () => System.Math.PI); + m_Consts.Add("e", () => System.Math.E); + m_Funcs.Add("sqrt", (p) => System.Math.Sqrt(p.FirstOrDefault())); + m_Funcs.Add("abs", (p) => System.Math.Abs(p.FirstOrDefault())); + m_Funcs.Add("ln", (p) => System.Math.Log(p.FirstOrDefault())); + m_Funcs.Add("floor", (p) => System.Math.Floor(p.FirstOrDefault())); + m_Funcs.Add("ceiling", (p) => System.Math.Ceiling(p.FirstOrDefault())); + m_Funcs.Add("round", (p) => System.Math.Round(p.FirstOrDefault())); + + m_Funcs.Add("sin", (p) => System.Math.Sin(p.FirstOrDefault())); + m_Funcs.Add("cos", (p) => System.Math.Cos(p.FirstOrDefault())); + m_Funcs.Add("tan", (p) => System.Math.Tan(p.FirstOrDefault())); + + m_Funcs.Add("asin", (p) => System.Math.Asin(p.FirstOrDefault())); + m_Funcs.Add("acos", (p) => System.Math.Acos(p.FirstOrDefault())); + m_Funcs.Add("atan", (p) => System.Math.Atan(p.FirstOrDefault())); + m_Funcs.Add("atan2", (p) => System.Math.Atan2(p.FirstOrDefault(),p.ElementAtOrDefault(1))); + //System.Math.Floor + m_Funcs.Add("min", (p) => System.Math.Min(p.FirstOrDefault(), p.ElementAtOrDefault(1))); + m_Funcs.Add("max", (p) => System.Math.Max(p.FirstOrDefault(), p.ElementAtOrDefault(1))); + m_Funcs.Add("rnd", (p) => + { + if (p.Length == 2) + return p[0] + rnd.NextDouble() * (p[1] - p[0]); + if (p.Length == 1) + return rnd.NextDouble() * p[0]; + return rnd.NextDouble(); + }); + } + + public void AddFunc(string aName, System.Func aMethod) + { + if (m_Funcs.ContainsKey(aName)) + m_Funcs[aName] = aMethod; + else + m_Funcs.Add(aName, aMethod); + } + + public void AddConst(string aName, System.Func aMethod) + { + if (m_Consts.ContainsKey(aName)) + m_Consts[aName] = aMethod; + else + m_Consts.Add(aName, aMethod); + } + public void RemoveFunc(string aName) + { + if (m_Funcs.ContainsKey(aName)) + m_Funcs.Remove(aName); + } + public void RemoveConst(string aName) + { + if (m_Consts.ContainsKey(aName)) + m_Consts.Remove(aName); + } + public bool containgsConst(string name){ + return m_Consts.ContainsKey (name); + } + + + int FindClosingBracket(ref string aText, int aStart, char aOpen, char aClose) + { + int counter = 0; + for (int i = aStart; i < aText.Length; i++) + { + if (aText[i] == aOpen) + counter++; + if (aText[i] == aClose) + counter--; + if (counter == 0) + return i; + } + return -1; + } + + void SubstitudeBracket(ref string aExpression, int aIndex) + { + int closing = FindClosingBracket(ref aExpression, aIndex, '(', ')'); + if (closing > aIndex + 1) + { + string inner = aExpression.Substring(aIndex + 1, closing - aIndex - 1); + m_BracketHeap.Add(inner); + string sub = "&" + (m_BracketHeap.Count - 1) + ";"; + aExpression = aExpression.Substring(0, aIndex) + sub + aExpression.Substring(closing + 1); + } + else throw new ParseException("Bracket not closed!"); + } + + IValue Parse(string aExpression) + { + aExpression = aExpression.Trim(); + int index = aExpression.IndexOf('('); + while (index >= 0) + { + SubstitudeBracket(ref aExpression, index); + index = aExpression.IndexOf('('); + } + if (aExpression.Contains(',')) + { + string[] parts = aExpression.Split(','); + List exp = new List(parts.Length); + for (int i = 0; i < parts.Length; i++) + { + string s = parts[i].Trim(); + if (!string.IsNullOrEmpty(s)) + exp.Add(Parse(s)); + } + return new MultiParameterList(exp.ToArray()); + } + else if (aExpression.Contains('+')) + { + string[] parts = aExpression.Split('+'); + List exp = new List(parts.Length); + for (int i = 0; i < parts.Length; i++) + { + string s = parts[i].Trim(); + if (!string.IsNullOrEmpty(s)) + exp.Add(Parse(s)); + } + if (exp.Count == 1) + return exp[0]; + return new OperationSum(exp.ToArray()); + } + else if (aExpression.Contains('-')) + { + string[] parts = aExpression.Split('-'); + List exp = new List(parts.Length); + if (!string.IsNullOrEmpty(parts[0].Trim())) + exp.Add(Parse(parts[0])); + for (int i = 1; i < parts.Length; i++) + { + string s = parts[i].Trim(); + if (!string.IsNullOrEmpty(s)) + exp.Add(new OperationNegate(Parse(s))); + } + if (exp.Count == 1) + return exp[0]; + return new OperationSum(exp.ToArray()); + } + else if (aExpression.Contains('*')) + { + string[] parts = aExpression.Split('*'); + List exp = new List(parts.Length); + for (int i = 0; i < parts.Length; i++) + { + exp.Add(Parse(parts[i])); + } + if (exp.Count == 1) + return exp[0]; + return new OperationProduct(exp.ToArray()); + } + else if (aExpression.Contains('/')) + { + string[] parts = aExpression.Split('/'); + List exp = new List(parts.Length); + if (!string.IsNullOrEmpty(parts[0].Trim())) + exp.Add(Parse(parts[0])); + for (int i = 1; i < parts.Length; i++) + { + if (parts[i].Trim() == "0") + throw new DivideByZeroException(); + + string s = parts[i].Trim(); + if (!string.IsNullOrEmpty(s)) + exp.Add(new OperationReciprocal(Parse(s))); + } + return new OperationProduct(exp.ToArray()); + } + else if (aExpression.Contains('^')) + { + int pos = aExpression.IndexOf('^'); + var val = Parse(aExpression.Substring(0, pos)); + var pow = Parse(aExpression.Substring(pos + 1)); + return new OperationPower(val, pow); + } + int pPos = aExpression.IndexOf("&"); + if (pPos > 0) + { + string fName = aExpression.Substring(0, pPos); + foreach (var M in m_Funcs) + { + if (fName == M.Key) + { + var inner = aExpression.Substring(M.Key.Length); + var param = Parse(inner); + var multiParams = param as MultiParameterList; + IValue[] parameters; + if (multiParams != null) + parameters = multiParams.Parameters; + else + parameters = new IValue[] { param }; + return new CustomFunction(M.Key, M.Value, parameters); + } + } + } + foreach (var C in m_Consts) + { + if (aExpression == C.Key) + { + return new CustomFunction(C.Key,(p)=>C.Value(),null); + } + } + int index2a = aExpression.IndexOf('&'); + int index2b = aExpression.IndexOf(';'); + if (index2a >= 0 && index2b >= 2) + { + var inner = aExpression.Substring(index2a + 1, index2b - index2a - 1); + int bracketIndex; + if (int.TryParse(inner, out bracketIndex) && bracketIndex >= 0 && bracketIndex < m_BracketHeap.Count) + { + return Parse(m_BracketHeap[bracketIndex]); + } + else + throw new ParseException("Can't parse substitude token"); + } + double doubleValue; + if (double.TryParse(aExpression, out doubleValue)) + { + return new Number(doubleValue); + } + if (ValidIdentifier(aExpression)) + { + if (m_Context.Parameters.ContainsKey(aExpression)) + return m_Context.Parameters[aExpression]; + var val = new Parameter(aExpression); + m_Context.Parameters.Add(aExpression, val); + return val; + } + + throw new ParseException("Reached unexpected end within the parsing tree"); + } + + private bool ValidIdentifier(string aExpression) + { + aExpression = aExpression.Trim(); + if (string.IsNullOrEmpty(aExpression)) + return false; + if (aExpression.Length < 1) + return false; + if (aExpression.Contains(" ")) + return false; + if (!"abcdefghijklmnopqrstuvwxyz§$".Contains(char.ToLower(aExpression[0]))) + return false; + if (m_Consts.ContainsKey(aExpression)) + return false; + if (m_Funcs.ContainsKey(aExpression)) + return false; + return true; + } + + public Expression EvaluateExpression(string aExpression) + { + var val = new Expression(); + m_Context = val; + val.ExpressionTree = Parse(aExpression); + m_Context = null; + m_BracketHeap.Clear(); + return val; + } + + public double Evaluate(string aExpression) + { + return EvaluateExpression(aExpression).Value; + } + public static double Eval(string aExpression) + { + return new ExpressionParser().Evaluate(aExpression); + } + + public class ParseException : System.Exception { public ParseException(string aMessage) : base(aMessage) { } } + } +} diff --git a/LineParser/Parsers/SumParser/MathParser.cs b/LineParser/Parsers/SumParser/MathParser.cs new file mode 100644 index 0000000..e161197 --- /dev/null +++ b/LineParser/Parsers/SumParser/MathParser.cs @@ -0,0 +1,10 @@ +using System; + +namespace Compiler +{ + public class MathParser + { + public static readonly char[] mathOperators = { '+', '-', '/', '*', '%', '^'}; + } +} + diff --git a/LineParser/Parsers/SumParser/NumberSumParser.cs b/LineParser/Parsers/SumParser/NumberSumParser.cs new file mode 100644 index 0000000..e515b1a --- /dev/null +++ b/LineParser/Parsers/SumParser/NumberSumParser.cs @@ -0,0 +1,155 @@ +using System; +using ErrorHandler; +using System.Collections.Generic; +using Runtime; + +namespace Compiler +{ + public class NumberSumParser{ + + public static Variable validNumberSum(Logic[] logicOrder, int lineNumber){ + handleFirstAndLastWords(logicOrder, lineNumber); + + logicOrder = calcPow (logicOrder, lineNumber); + logicOrder = calcModulo (logicOrder, lineNumber); + + var calcString = LogicToCalcString(logicOrder, out bool corrupt); + + if (!corrupt) + try{ + double returnResult = SyntaxCheck.globalParser.Evaluate(calcString); + return new Variable ("calcVarMaten", returnResult, true); + } + catch(Exception e){ + if (e is DivideByZeroException) + ErrorMessage.sendErrorMessage(lineNumber, "Kan inte dividera med noll!"); + ErrorMessage.sendErrorMessage (lineNumber, "Något gick fel i uträkningen: " + e.ToString()); + } + + + ErrorMessage.sendErrorMessage (lineNumber, "Något gick fel med nummertolkningen"); + return new Variable (); + } + + #region pow "**" + private static Logic[] calcPow(Logic[] logicOrder, int lineNumber){ + List postPower = new List (); + + for (int i = 0; i < logicOrder.Length; i++) { + if (logicOrder [i].currentType == WordTypes.mathOperator && logicOrder [i].word == "*" && i < logicOrder.Length - 1) { + if (logicOrder [i+1].currentType == WordTypes.mathOperator && logicOrder [i+1].word == "*") { + postPower.Add (new MathOperator ("^")); + i++; + } + else + postPower.Add (logicOrder[i]); + } + else + postPower.Add (logicOrder[i]); + } + + return postPower.ToArray (); + } + #endregion + + + #region Modulo + private static Logic[] calcModulo(Logic[] logicOrder, int lineNumber){ + List postModulo = new List (); + + for (int i = 0; i < logicOrder.Length; i++) { + + if (logicOrder [i].currentType == WordTypes.mathOperator && logicOrder [i].word == "%") { + + if (i <= 0 || i >= logicOrder.Length - 1) + ErrorMessage.sendErrorMessage (lineNumber, "Modulo operatorn måste appliceras på två tal"); + + if(logicOrder[i-1].currentType != WordTypes.variable && logicOrder[i-1].currentType != WordTypes.number) + // Will not be reached because there can't be a number and a notNumber at the same row + ErrorMessage.sendErrorMessage (lineNumber, "Modulo operatorn måste appliceras på två tal"); + + double firstValue = getNumberValue (logicOrder [i - 1]); + double secondValue = getNumberValue (logicOrder [i + 1]); + double result = firstValue % secondValue; + + postModulo.RemoveAt (postModulo.Count - 1); + postModulo.Add (new NumberValue (result)); + i++; + } + else + postModulo.Add (logicOrder [i]); + } + + return postModulo.ToArray (); + } + + private static double getNumberValue(Logic l){ + if (l.currentType == WordTypes.variable) + return (l as Variable).getNumber (); + + return (l as NumberValue).value; + } + #endregion + + private static void handleFirstAndLastWords(Logic[] logicOrder, int lineNumber){ + string firstWord = logicOrder [0].word; + string lastWord = logicOrder [logicOrder.Length - 1].word; + + if (lastWord == "*" || lastWord == "/") + ErrorMessage.sendErrorMessage (lineNumber, "Matematiska uttryck kan inte sluta med \"" + lastWord + "\""); + if (firstWord == "*" || firstWord == "/") + ErrorMessage.sendErrorMessage (lineNumber, "Matematiska uttryck kan inte börja med \"" + firstWord + "\""); + + } + + private static string LogicToCalcString(Logic[] logicOrder, out bool corrupt) + { + string calcString = ""; + corrupt = false; + + for (int i = 0; i < logicOrder.Length; i++) + { + if (logicOrder[i].currentType == WordTypes.variable) + { + if (shouldAddParenthesis(logicOrder, i)) + calcString += "(" + (logicOrder[i] as Variable).getNumber() + ")"; + else + calcString += (logicOrder[i] as Variable).getNumber().ToString(); + } + else if (logicOrder[i].currentType == WordTypes.number) + { + if (shouldAddParenthesis(logicOrder, i)) + { + calcString = calcString.Remove(calcString.Length - 1); + calcString += "(-" + logicOrder[i].word + ")"; + } + else + calcString += logicOrder[i].word; + } + else if (logicOrder[i].currentType == WordTypes.mathOperator) + calcString += logicOrder[i].word; + else + corrupt = true; + } + + return calcString; + } + + private static bool shouldAddParenthesis(Logic[] logicOrder, int index) + { + if (index > 2 && + logicOrder[index - 1].word == "-" && + logicOrder[index - 2].currentType != WordTypes.number && + logicOrder[index - 2].currentType != WordTypes.variable) + return true; + + if (logicOrder[index].currentType == WordTypes.variable && + (logicOrder[index] as Variable).variableType == VariableTypes.number && + (logicOrder[index] as Variable).getNumber() < 0) + return true; + return false; + } + } + +} + diff --git a/LineParser/Parsers/SumParser/StatementParser.cs b/LineParser/Parsers/SumParser/StatementParser.cs new file mode 100644 index 0000000..b5a26d8 --- /dev/null +++ b/LineParser/Parsers/SumParser/StatementParser.cs @@ -0,0 +1,157 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class StatementParser{ + + public static bool parseAndCheckStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + Variable sum = SumParser.parseIntoSum (logicOrder, lineNumber, currentScope); + + if (sum.variableType == VariableTypes.number){ + if (sum.getNumber() == 0) + return false; + else + return true; + } + + if (sum.variableType == VariableTypes.textString) { + if (sum.getString () == "") + return false; + else + return true; + } + + if (sum.variableType == VariableTypes.None) + return false; + + if (sum.variableType != VariableTypes.boolean) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.IfStatements, IfErrorType.expressionNotCorrectType.ToString(), null); + + return sum.getBool (); + } + + + public static bool parseStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + BoolAlgebraWord[] algebra = BoolAlgebraParser.parseIntoBoolAlgebra (logicOrder, lineNumber, currentScope); + return BoolAlgebraParser.parseBoolAlgebraStatement (algebra, lineNumber); + } + + public static bool parseExpression(Logic[] logicOrder, int lineNumber, Scope currentScope){ + #region findOperators + int operatorLow = -1; + int operatorHigh = -1; + int operatorAmount = 0; + for (int i = 0; i < logicOrder.Length; i++) + if (isStatementOperator (logicOrder [i])) { + if (operatorLow == -1) + operatorLow = i; + else + operatorHigh = i; + operatorAmount++; + } + + + #endregion + + + if (operatorAmount > 2 && operatorHigh - operatorLow != 1) { + ErrorMessage.sendErrorMessage (lineNumber, "I detta moment är det inte tillåtet att gör flera jämförelser direkt efter varandra. Använd \"and\" och \"or\" istället."); + } + if (operatorAmount == 0) + return handleOnlyValueStatement (logicOrder, lineNumber, currentScope); + + if (operatorAmount == 2) { + if (operatorHigh - operatorLow != 1) + ErrorMessage.sendErrorMessage (lineNumber, "Operatorerna måste komma direkt efter varandra"); + } + else + operatorHigh = operatorLow; + + + + + + Logic[] leftSide = new Logic[operatorLow]; + Logic[] rightSide = new Logic[logicOrder.Length - 1 - operatorHigh]; + Logic[] operators = new Logic[operatorAmount]; + setSidesOfStatement (logicOrder, leftSide, rightSide, operators, operatorLow, operatorHigh); + + + Variable firstSum = SumParser.parseIntoSum (leftSide, lineNumber, currentScope); + Variable secondSum = SumParser.parseIntoSum (rightSide, lineNumber, currentScope); + ComparisonType operatorType = ComparisonOperatorParser.parseOperators (operators); + + if (operatorType == ComparisonType.unknown) { + if (operators[0].currentType == WordTypes.equalSign) + ErrorMessage.sendErrorMessage(lineNumber, "Fel vid tilldelning. Kom ihåg att använda == om du vill jämföra om två värden är lika."); + else + ErrorMessage.sendErrorMessage(lineNumber, "Operatorerna går inte att tyda"); + } + + if (firstSum.variableType == VariableTypes.unknown || secondSum.variableType == VariableTypes.unknown) + ErrorMessage.sendErrorMessage (lineNumber, "Korrupt värde"); + + if (firstSum.variableType != secondSum.variableType) + { + var firstSumType = SumParser.TypeToString(firstSum.variableType); + var secondSumType = SumParser.TypeToString(secondSum.variableType); + + string errorMessage; + + if (firstSumType == "" || secondSumType == "") + errorMessage = "Misslyckades med att jämföra " + firstSum.variableType + " med " + secondSum.variableType; + else + errorMessage = "Kan inte jämföra " + firstSumType + " med " + secondSumType + "."; + + ErrorMessage.sendErrorMessage(lineNumber, errorMessage); + } + + if (ComparisonOperatorParser.checkSumsToOperator(firstSum.variableType, operatorType,lineNumber)) { + bool resultOfComparison = ComparisonOperatorParser.makeComparison (firstSum, secondSum, operatorType, lineNumber); + return resultOfComparison; + } + + ErrorMessage.sendErrorMessage (lineNumber, "Korrupt expression!"); + return false; + } + + public static bool isStatementOperator(Logic currentLogic){ + if (currentLogic.currentType == WordTypes.equalSign) + return true; + + if (currentLogic.currentType == WordTypes.lessThenSign || currentLogic.currentType == WordTypes.greaterThenSign) + return true; + + if (currentLogic.currentType == WordTypes.xorOperator) + return true; + + return false; + } + + + static void setSidesOfStatement(Logic[] logicOrder, Logic[] leftSide, Logic[] rightSide, Logic[] operators, int operatorLow, int operatorHigh){ + for (int i = 0; i < leftSide.Length; i++) + leftSide [i] = logicOrder [i]; + + for (int i = operatorHigh+1; i < logicOrder.Length; i++) + rightSide [i - (operatorHigh+1)] = logicOrder [i]; + + for (int i = operatorLow; i <= operatorHigh; i++) + operators [i - operatorLow] = logicOrder [i]; + } + + static bool handleOnlyValueStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + + Variable sum = SumParser.parseIntoSum (logicOrder, lineNumber, currentScope); + + if (sum.variableType != VariableTypes.boolean) + ErrorMessage.sendErrorMessage (lineNumber, "När du skriver in endast ett värde, måste det vara Sant eller Falskt"); + + return sum.getBool (); + } + } + +} + diff --git a/LineParser/Parsers/SumParser/SumParser.cs b/LineParser/Parsers/SumParser/SumParser.cs new file mode 100644 index 0000000..7a52b6f --- /dev/null +++ b/LineParser/Parsers/SumParser/SumParser.cs @@ -0,0 +1,256 @@ +using System; +using System.Linq; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class SumParser{ + + + public static Variable parseIntoSum(Logic[] logicOrderInput, int lineNumber, Scope currentScope){ + Logic[] logicOrder = (Logic[])logicOrderInput.Clone (); + UnpackPackages (logicOrder, lineNumber, currentScope); + + logicOrder = BoolCompressExpressions.compressExpression (logicOrder, lineNumber, currentScope, true); + logicOrder = BoolExpressionParser.compressAndOrStatements (logicOrder, lineNumber, currentScope); + + if (logicOrder.Length == 0) + return new Variable("CalcVar"); + + expectType theExpectedType = new expectType (); + calcSumType (logicOrder, theExpectedType, lineNumber, currentScope); + return getCalcSum (theExpectedType, logicOrder, lineNumber); + } + + private static void UnpackPackages(Logic[] PrelogicOrder, int lineNumber, Scope currentScope){ + for (int i = 0; i < PrelogicOrder.Length; i++) + if (PrelogicOrder [i].currentType == WordTypes.package) { + PrelogicOrder[i] = parseIntoSum ((PrelogicOrder[i] as Package).getLatestOrder(), lineNumber, currentScope); + } + } + + + private static void calcSumType(Logic[] logicOrder, expectType theExpectedType, int lineNumber, Scope currentScope){ + for(int i = 0; i < logicOrder.Length; i++){ + switch (logicOrder [i].currentType) { + + #region values + case WordTypes.textString: + setNewExpectVariable (theExpectedType, VariableTypes.textString, lineNumber); + break; + case WordTypes.number: + setNewExpectVariable (theExpectedType, VariableTypes.number, lineNumber); + break; + case WordTypes.booleanValue: + setNewExpectVariable (theExpectedType, VariableTypes.boolean, lineNumber); + break; + #endregion + + // booleanExpressions are for example a expression used in an if-statement + case WordTypes.booleanExpression: + logicOrder [i] = (logicOrder [i] as BooleanExpression).parseExpression (); + setNewExpectVariable (theExpectedType, VariableTypes.boolean, lineNumber); + break; + + case WordTypes.variable: + handleVariable(logicOrder, theExpectedType, lineNumber, currentScope, i); + break; + + case WordTypes.functionCall: + handleFunctionCall(logicOrder, theExpectedType, lineNumber, currentScope, i); + break; + } + } + } + + private static void handleFunctionCall(Logic[] logicOrder, expectType theExpectedType, int lineNumber, Scope currentScope, int i){ + FunctionParser.linkFunctionCall ((logicOrder [i] as FunctionCall), lineNumber, currentScope); + + if ((logicOrder [i] as FunctionCall).targetFunc.isUserFunction) { + currentScope.getCurrentLine ().insertReturnExpect (logicOrder [i]); + (logicOrder [i] as FunctionCall).runFunction (currentScope); + + throw new FunctionCallException (); + } else { + if ((logicOrder [i] as FunctionCall).targetFunc.pauseWalker) + CodeWalker.pauseWalker (); + + if ((logicOrder[i] as FunctionCall).targetFunc.name == "input"){ + CodeWalker.linkSubmitInput.Invoke(SubmitInput, currentScope); + + Variable returnVariable = (logicOrder[i] as FunctionCall).runFunction(currentScope); + logicOrder[i] = returnVariable; + + if (returnVariable.variableType == VariableTypes.boolean) + setNewExpectVariable(theExpectedType, VariableTypes.boolean, lineNumber); + else if (returnVariable.variableType == VariableTypes.number) + setNewExpectVariable(theExpectedType, VariableTypes.number, lineNumber); + else if (returnVariable.variableType == VariableTypes.textString) + setNewExpectVariable(theExpectedType, VariableTypes.textString, lineNumber); + + CodeWalker.isWaitingForUserInput = true; + } + else { + Variable returnVariable = (logicOrder[i] as FunctionCall).runFunction(currentScope); + logicOrder[i] = returnVariable; + + if (returnVariable.variableType == VariableTypes.boolean) + setNewExpectVariable(theExpectedType, VariableTypes.boolean, lineNumber); + else if (returnVariable.variableType == VariableTypes.number) + setNewExpectVariable(theExpectedType, VariableTypes.number, lineNumber); + else if (returnVariable.variableType == VariableTypes.textString) + setNewExpectVariable(theExpectedType, VariableTypes.textString, lineNumber); + } + } + } + + private static void handleVariable(Logic[] logicOrder, expectType theExpectedType, int lineNumber, Scope currentScope, int i){ + int varPos = currentScope.scopeVariables.containsVariable ((logicOrder [i] as Variable).name); + if (varPos >= 0) { + Variable foundVar = currentScope.scopeVariables.variableList [varPos]; + setNewExpectVariable (theExpectedType, foundVar.variableType, lineNumber); + logicOrder [i] = foundVar; + } + else { + if ((logicOrder [i] as Variable).isCalcVar) + setNewExpectVariable (theExpectedType, (logicOrder [i] as Variable).variableType, lineNumber); + else{ + if((logicOrder [i] as Variable).name.Length > 10) + ErrorMessage.sendErrorMessage (lineNumber, "Användning av icke deklarerad variabel!"); + + LevenshteinDist.checkForClosesVariable (logicOrder [i].word, lineNumber, currentScope); + ErrorMessage.sendErrorMessage (lineNumber, "Kunde inte hitta variabeln \"" + (logicOrder [i] as Variable).name + "\" i minnet."); + } + } + } + + private static Variable getCalcSum(expectType theExpectedType, Logic[] logicOrder, int lineNumber){ + if (theExpectedType.currentType == VariableTypes.boolean) { + Variable sumVar = BooleanSumParser.validBoolSum (logicOrder, lineNumber); + if (sumVar.variableType == VariableTypes.boolean) + return sumVar; + } + + if (theExpectedType.currentType == VariableTypes.textString) { + Variable sumVar = TextSumParser.validTextSum (logicOrder, lineNumber); + if (sumVar.variableType == VariableTypes.textString) + return sumVar; + } + + if (theExpectedType.currentType == VariableTypes.number) { + Variable sumVar = NumberSumParser.validNumberSum (logicOrder, lineNumber); + if (sumVar.variableType == VariableTypes.number) + return sumVar; + } + + return new Variable ("CalcVar"); + } + + public static void SubmitInput(string inputFromUser, Scope currentScope){ + if (!CodeWalker.isWaitingForUserInput) + return; + + CodeWalker.isWaitingForUserInput = false; + + var oldLine = currentScope.getCurrentLine().cloneLine(); + var oldLineString = oldLine.getFullLine(); + var newLine = ReplaceInputWithValue(oldLineString, inputFromUser); + + var lines = SyntaxCheck.parseLines(newLine); + var words = lines.First().words; + var logic = WordsToLogicParser.determineLogicFromWords(words, 1, currentScope); + + currentScope.getCurrentLine().words = words; + currentScope.getCurrentLine().logicOrder = logic; + + CodeWalker.parseLine(currentScope.getCurrentLine(), oldLine); + } + + private static string ReplaceInputWithValue(string currentLine, string value){ + var currentCharIndex = 0; + var inputStartIndex = -1; + var inputEndIndex = -1; + var startedParanthesis = -1; + + while (currentCharIndex < currentLine.Length){ + + if (currentLine[currentCharIndex] == 'i' && currentLine[currentCharIndex + 1] == 'n' && currentLine[currentCharIndex + 2] == 'p' && + currentLine[currentCharIndex + 3] == 'u' && currentLine[currentCharIndex + 4] == 't' && currentLine[currentCharIndex + 5] == '('){ + + inputStartIndex = currentCharIndex; + startedParanthesis = 1; + currentCharIndex += 6; + } + + if (currentLine[currentCharIndex] == '(') + startedParanthesis++; + else if (currentLine[currentCharIndex] == ')') + startedParanthesis--; + + if (startedParanthesis == 0) + inputEndIndex = currentCharIndex + 1; + + currentCharIndex++; + } + + var subStringLength = inputEndIndex - inputStartIndex; + var subStringWithInput = currentLine.Substring(inputStartIndex, subStringLength); + + var firstPartSubString = currentLine.Substring(0, inputStartIndex); + var secondPartSubString = currentLine.Substring(inputEndIndex); + + var newLine = firstPartSubString + "\"" + value + "\"" + secondPartSubString; + + return newLine; + } + + #region Expected type + private class expectType + { + public VariableTypes currentType; + public expectType(){ + currentType = VariableTypes.unsigned; + } + } + + private static void setNewExpectVariable(expectType expect, VariableTypes newType, int lineNumber){ + if (expect.currentType == VariableTypes.unsigned) + expect.currentType = newType; + else if (expect.currentType != newType) { + var firstSumType = TypeToString(expect.currentType); + var secondSumType = TypeToString(newType); + + string errorMessage; + + if (firstSumType == "" || secondSumType == "") + errorMessage = "Misslyckades med att para ihop " + expect.currentType + " med " + newType; + else + errorMessage = "Kan inte lägga ihop " + firstSumType + " med " + secondSumType + "."; + + ErrorMessage.sendErrorMessage (lineNumber, errorMessage); + expect.currentType = VariableTypes.unknown; + } + } + #endregion + + public static string TypeToString(VariableTypes variableType) + { + if (variableType == VariableTypes.number) + return "ett tal"; + if (variableType == VariableTypes.textString) + return "en sträng"; + if (variableType == VariableTypes.boolean) + return "ett boolskt värde"; + if (variableType == VariableTypes.None) + return "None"; + if (variableType == VariableTypes.unknown) + return "ett okänt värde"; + if (variableType == VariableTypes.unsigned) + return "ett odefinierat värde"; + return ""; + } + } + +} + diff --git a/LineParser/Parsers/SumParser/TextSumParser.cs b/LineParser/Parsers/SumParser/TextSumParser.cs new file mode 100644 index 0000000..606f3c1 --- /dev/null +++ b/LineParser/Parsers/SumParser/TextSumParser.cs @@ -0,0 +1,93 @@ +using System; +using ErrorHandler; + +namespace Compiler +{ + + internal class TextSumParser{ + + public static Variable validTextSum(Logic[] logicOrder, int lineNumber){ + + if (logicOrder.Length < 1) + return new Variable("Unknown Variable"); + + + string returnValue = ""; + bool corrupt = false; + + for (int i = 0; i < logicOrder.Length; i++) { + + if (i % 2 == 1) { + if (!isPlusSign (logicOrder [i], lineNumber)) { + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.Text, TextErrorType.expectedPlusSignBetweenStrings.ToString(), null); + corrupt = true; + break; + } + } + else { + if (isStringType (logicOrder [i], lineNumber)) + returnValue += getStringValue (logicOrder [i]); + + else { + // Can never reach this? + corrupt = true; + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.Text, TextErrorType.expectedATextValue.ToString(), null); + } + } + } + + + //Check so it ends with a String + if(isStringType( logicOrder[logicOrder.Length -1], lineNumber) == false){ + corrupt = true; + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.Text, TextErrorType.expressionNeedsToEndWithAString.ToString(), null); + } + + + if (corrupt) { + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.textParsingMalfunction.ToString(), null); + return new Variable ("Unknown Variable"); + } + else + return new Variable ("TextVar", returnValue, true); + } + + + + static bool isPlusSign(Logic currentLogic, int lineNumber){ + if (currentLogic.currentType == WordTypes.mathOperator) + if ((currentLogic as MathOperator).word == "+") + return true; + + return false; + } + + static bool isStringType(Logic currentLogic, int lineNumber){ + if (currentLogic.currentType == WordTypes.textString) + return true; + + if (currentLogic.currentType == WordTypes.variable) { + + if ((currentLogic as Variable).variableType == VariableTypes.textString) + return true; + } + + + return false; + } + + static string getStringValue(Logic currentLogic){ + if (currentLogic.currentType == WordTypes.textString) + return (currentLogic as TextValue).value; + + if (currentLogic.currentType == WordTypes.variable) + if ((currentLogic as Variable).variableType == VariableTypes.textString) + return (currentLogic as Variable).getString(); + + return ""; + } + + } + +} + diff --git a/LineParser/Parsers/SumParser/ValidSumCheck.cs b/LineParser/Parsers/SumParser/ValidSumCheck.cs new file mode 100644 index 0000000..6dcb0f9 --- /dev/null +++ b/LineParser/Parsers/SumParser/ValidSumCheck.cs @@ -0,0 +1,103 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class ValidSumCheck{ + + + public static Variable checkIfValidSum(Logic[] PrelogicOrder, int lineNumber){ + Logic[] logicOrder = (Logic[])PrelogicOrder.Clone (); + UnpackPackages (logicOrder, lineNumber); + + logicOrder = BoolCompressExpressions.compressExpression (logicOrder, lineNumber, null, false); + logicOrder = BoolExpressionParser.compressAndOrStatements (logicOrder, lineNumber, null); + + if (logicOrder.Length == 0) + return new Variable("No var"); + + expectType theExpectedType = new expectType (); + + for(int i = 0; i < logicOrder.Length; i++){ + + if(logicOrder[i].currentType == WordTypes.booleanExpression) + setNewExpectVariable (theExpectedType, VariableTypes.boolean, lineNumber, logicOrder); + + else if (logicOrder [i].currentType == WordTypes.variable) + logicOrder [i] = new Variable (logicOrder [i].word); + else if (logicOrder [i].currentType == WordTypes.mathOperator) { + + } + else if (logicOrder [i].currentType == WordTypes.number) + setNewExpectVariable (theExpectedType, VariableTypes.number, lineNumber, logicOrder); + else if (logicOrder [i].currentType == WordTypes.textString) + setNewExpectVariable (theExpectedType, VariableTypes.textString, lineNumber, logicOrder); + else if (logicOrder [i].currentType == WordTypes.booleanValue) + setNewExpectVariable (theExpectedType, VariableTypes.boolean, lineNumber, logicOrder); + } + + if (theExpectedType.currentType == VariableTypes.unknown) + return new Variable (); + + return theExpectedType.returnExpectedVariable(); + } + + private static void UnpackPackages(Logic[] PrelogicOrder, int lineNumber){ + for(int i = 0; i < PrelogicOrder.Length; i++) + if (PrelogicOrder[i].currentType == WordTypes.package) + PrelogicOrder[i] = checkIfValidSum ((PrelogicOrder[i] as Package).getLatestOrder(), lineNumber); + } + + + #region Expect type + static void setNewExpectVariable(expectType expect, VariableTypes newType, int lineNumber, Logic[] logicOrder){ + if (expect.currentType == VariableTypes.unknown) + return; + + if (expect.currentType == VariableTypes.unsigned) + expect.currentType = newType; + else if (expect.currentType != newType) + { + var firstSumType = SumParser.TypeToString(expect.currentType); + var secondSumType = SumParser.TypeToString(newType); + + string errorMessage; + + if (firstSumType == "" || secondSumType == "") + errorMessage = "Misslyckades med att para ihop " + expect.currentType + " med " + newType; + else + errorMessage = "Kan inte para ihop " + firstSumType + " med " + secondSumType + "."; + + ErrorMessage.sendErrorMessage (lineNumber, errorMessage); + } + + if (expect.currentType == VariableTypes.boolean) + BooleanSumParser.validBoolSum (logicOrder, lineNumber); + } + + + private class expectType + { + public VariableTypes currentType; + public expectType(){ + currentType = VariableTypes.unsigned; + } + + public Variable returnExpectedVariable(){ + if (currentType == VariableTypes.boolean) + return new Variable ("Type Variable", false); + if (currentType == VariableTypes.number) + return new Variable ("Type Variable", 0); + if (currentType == VariableTypes.textString) + return new Variable ("Type Variable", ""); + + return new Variable ("Type Variable"); + } + } + #endregion + + } + +} + diff --git a/LineParser/Parsers/Words.cs b/LineParser/Parsers/Words.cs new file mode 100644 index 0000000..1cf659c --- /dev/null +++ b/LineParser/Parsers/Words.cs @@ -0,0 +1,12 @@ +using System; + +namespace LineParser +{ + public class Words + { + public Words () + { + } + } +} + diff --git a/LineParser/Parsers/Words/WordParser.cs b/LineParser/Parsers/Words/WordParser.cs new file mode 100644 index 0000000..55f2aec --- /dev/null +++ b/LineParser/Parsers/Words/WordParser.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; + +namespace Compiler +{ + public class WordParser { + + //Parses entered text into a string array of all the seperate words entered + + private static char[] saveOperators = { ':', '=', '!', ',', '>', '<' }; + + //Everything included into Parentheses will be returnd as ONE word. + //The logic for this word will later be *Package*. + + internal static string[] parseWords(string trimedString){ + + List words = new List (); + + int lastBreak = -1; + int foundLetters = 0; + int functionParantes = 0; + int functionQoutes = 0; + for (int i = 0; i < trimedString.Length; i++) { + + + //Checks if current Char is a "BreakWordChar" meaning it stops the current word recording. + if (isBreakWordChar (trimedString [i], functionParantes, functionQoutes)) { + + if (foundLetters > 0) { + string temp = trimedString.Substring (lastBreak + 1, foundLetters); + words.Add (temp); + } + + foundLetters = 0; + lastBreak = i; + + //If the current breakchar is worth saving! + if (isSaveOperator (trimedString [i])) { + string temp = ""; + temp += trimedString [i]; + words.Add (temp); + } + } else { + functionQoutes = isInFunctionQuotes (trimedString [i], functionQoutes); + functionParantes += isInFunctionParameter (trimedString [i], foundLetters, functionQoutes); + foundLetters++; + } + + + } + + if (foundLetters > 0) { + string temp = trimedString.Substring (lastBreak + 1, foundLetters); + words.Add (temp); + } + + + return words.ToArray (); + } + + + + + #region char checks + static bool isSaveOperator(char c){ + + foreach (char Operator in saveOperators) + if (c == Operator) + return true; + + for(int i = 0; i < MathParser.mathOperators.Length; i++) + if(c == MathParser.mathOperators[i]) + return true; + + return false; + } + + + static int isInFunctionQuotes(char c, int functionQoutes){ + + if (c == '"') { + if (functionQoutes > 0) + return 0; + else + return 1; + } + return functionQoutes; + + } + + static int isInFunctionParameter(char c, int foundLetters, int functionQoutes){ + + if (functionQoutes > 0) + return 0; + + if (c == '(') + return 1; + + if (c == ')') + return -1; + + return 0; + } + + + static bool isBreakWordChar(char c, int functionParantes, int functionQoutes){ + if (c == '\n') + return true; + + if (functionParantes > 0 || functionQoutes > 0) + return false; + + + if (c == ' ' || c == '\t') + return true; + + if (c == ':' || c == '=' || c == '!' || c == ',' || c == '>' || c == '<' ) + return true; + + + for(int i = 0; i < MathParser.mathOperators.Length; i++) + if(c == MathParser.mathOperators[i]) + return true; + + return false; + } + #endregion + } + +} + diff --git a/LineParser/Properties/AssemblyInfo.cs b/LineParser/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c00f166 --- /dev/null +++ b/LineParser/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("Compiler")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("FreddeFrallan")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/LineParser/Runtime/CodeWalker.cs b/LineParser/Runtime/CodeWalker.cs new file mode 100644 index 0000000..3f5b8a7 --- /dev/null +++ b/LineParser/Runtime/CodeWalker.cs @@ -0,0 +1,282 @@ +using Compiler; +using ErrorHandler; +using System; +using System.Linq; + +namespace Runtime +{ + public class CodeWalker + { + private static Scope currentScope; + private static int currentLineIndex = 0; + private static Scope returnTarget; + private static bool isReturning = false; + + public static bool switchedToUserFunc = false; + public static bool isWaitingForUserInput; + + internal static Action doEndWalker, pauseWalker, activateFunctionColor; + internal static Action, Scope> linkSubmitInput; + static Action showCurrentActiveCodeLine; + + #region initWalker + /// + /// Setup for CodeWalker. + /// + public static void setActions(Action endWalker, Action walkerPause, Action, Scope> linkInputTrigger, Action funcColor, Action showCurrentLine, Scope main){ + doEndWalker = endWalker; + pauseWalker = walkerPause; + linkSubmitInput = linkInputTrigger; + activateFunctionColor = funcColor; + showCurrentActiveCodeLine = showCurrentLine; + currentScope = main; + isWaitingForUserInput = false; + currentLineIndex = 0; + } + #endregion + + + #region runtime + public static void parseLine(){ + if (handleReturn ()) + return; + + if (currentLineIndex >= currentScope.codeLines.Count) + if (currentScope.parentScope == null) { + doEndWalker.Invoke (); + return; + } + else { + SetFinalScopeCommands (false, currentScope.codeLines[currentScope.codeLines.Count-1].lineNumber); + return; + } + + if (!isWaitingForUserInput) + currentScope.lastReadLine = currentLineIndex; + + CodeLine currentLine = currentScope.getCurrentLine (); + + if (currentLine.logicOrder [0] is ScopeStarter) { + + if ((currentLine.logicOrder [0] as ScopeStarter).doParseLine == false) { + currentLineIndex++; + parseLine(); + return; + } + } + + showCurrentActiveCodeLine.Invoke (currentLine.lineNumber); + + try{ + currentLine.theCommandType = parseCommandType (currentLine.lineNumber, currentScope); + } + catch(Exception e){ + if (e is FunctionCallException) + return; + throw e; + } + + if (!isWaitingForUserInput) + { + ReturnMemoryClear.clearLineMemory (currentLine); + + //Enter New Scope + if ((currentLine.logicOrder[0] is ScopeStarter) && NTScopeStarter (currentLine)) + return; + + VariableWindow.sendStackVariables (currentScope); + currentLineIndex++; + } + } + + public static void parseLine(CodeLine currentLine, CodeLine originalLine){ + if (handleReturn()) + return; + + if (currentLineIndex >= currentScope.codeLines.Count) + if (currentScope.parentScope == null) + { + doEndWalker.Invoke(); + return; + } + else + { + SetFinalScopeCommands(false, currentScope.codeLines[currentScope.codeLines.Count - 1].lineNumber); + return; + } + + currentScope.lastReadLine = currentLineIndex; + + if (currentLine.logicOrder[0] is ScopeStarter){ + + if ((currentLine.logicOrder[0] as ScopeStarter).doParseLine == false) + { + currentLineIndex++; + parseLine(); + return; + } + } + + showCurrentActiveCodeLine.Invoke(currentLine.lineNumber); + + try{ + currentLine.theCommandType = parseCommandType(currentLine.lineNumber, currentScope); + } + catch (Exception e){ + if (e is FunctionCallException) + return; + throw e; + } + + ReturnMemoryClear.clearLineMemory(currentLine); + + //Enter New Scope + if ((currentLine.logicOrder[0] is ScopeStarter) && NTScopeStarter(currentLine)) + return; + + VariableWindow.sendStackVariables(currentScope); + currentLineIndex++; + + // Reset current line so input can be run again if line is inside loop + currentScope.setCurrentLine(originalLine); + } + #endregion + + + #region internal public methods + internal static void switchToUserFunc(Scope current, Scope target){ + switchedToUserFunc = true; + target.parentScope = current; + setScopeToParse (target, current); + } + + internal static void setScopeToParse(Scope newScope, Scope parentScope){ + newScope.parentScope = parentScope; + currentScope = newScope; + currentLineIndex = 0; + } + + internal static void breakLoop(Scope targetLoop, int lineNumber){ + currentScope.upInheritVariable (targetLoop); + currentScope = targetLoop; + SetFinalScopeCommands (true, lineNumber); + throw new FunctionCallException(); + } + + internal static void continueLoop(Scope targetLoop, int lineNumber){ + currentScope.upInheritVariable (targetLoop); + currentScope = targetLoop; + SetFinalScopeCommands (false, lineNumber); + throw new FunctionCallException(); + } + #endregion + + + + #region runtime backend logic + + #region finalCommands + private static void SetFinalScopeCommands(bool forceQuit, int lineNumber){ + + if ((currentScope.theScopeType == ScopeType.forLoop || currentScope.theScopeType == ScopeType.whileLoop)) { + bool doLoopAgain = forceQuit ? false : (currentScope.theScoopLoop as Loop).makeComparison (currentScope.codeLines [0].lineNumber); + if (doLoopAgain) { + currentLineIndex = 0; + return; + } + } + + if (currentScope.theScopeType != ScopeType.main) { + currentScope = findTargetParentScope (currentScope, lineNumber); + currentLineIndex = currentScope.lastReadLine + 1; + parseLine (); + } + else + doEndWalker.Invoke (); + } + + + private static Scope findTargetParentScope(Scope currentScope, int lineNumber){ + if (currentScope.parentScope == null) + ErrorMessage.sendErrorMessage (lineNumber, "Parent scope is missing"); + + if (currentScope.theScopeType != ScopeType.function) + currentScope.upInheritVariable (currentScope.parentScope); + + if (currentScope.parentScope.lastReadLine != currentScope.parentScope.codeLines.Count - 1 || currentScope.parentScope.theScopeType == ScopeType.main) + return currentScope.parentScope; + + if (currentScope.parentScope.theScoopLoop != null && (currentScope.parentScope.theScoopLoop as Loop).makeComparison (lineNumber)) { + currentScope.parentScope.lastReadLine = -1; + return currentScope.parentScope; + } + + return findTargetParentScope (currentScope.parentScope, lineNumber); + } + #endregion + + + private static Logic parseCommandType(int lineNumber, Scope currentScope){ + CodeLine currentLine = currentScope.getCurrentLine (); + Logic[] logicOrder = currentLine.getLatestOrder(); + checkForUnknown (logicOrder, lineNumber); + + Logic result = VariableDeclareParser.checkForVariableDecleration (logicOrder, lineNumber, currentScope); + if(result.currentType != WordTypes.unknown) + return result; + + result = SpecialWordParser.parseSpecialLine (logicOrder, lineNumber, currentScope); + if(result.currentType != WordTypes.unknown) + return result; + + result = PureFunctionCallParser.parsePureFunctionCall (logicOrder, lineNumber, currentScope); + if(result.currentType != WordTypes.unknown) + return result; + + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.unknownLogic.ToString(), new string[]{"2"}); + return new UnknownLogic(lineNumber); + } + + private static void checkForUnknown(Logic[] logicOrder, int lineNumber){ + foreach (Logic L in logicOrder) + if (L.currentType == WordTypes.unknown) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.unknownLogic.ToString(), new string[]{"3"}); + } + + private static bool NTScopeStarter(CodeLine tempLine){ + Logic currentScopeStarter = tempLine.theCommandType; + + + if((currentScopeStarter as ScopeStarter).doEnterScope){ + Scope targetScope = (currentScopeStarter as ScopeStarter).getTargetScope(); + targetScope.scopeFunctions.savedFunctions = currentScope.scopeFunctions.getShallowCopy(); + targetScope.giveInheritVariables (currentScope.scopeVariables.variableList); + setScopeToParse (targetScope, currentScope); + return true; + } + return false; + } + + + private static bool handleReturn(){ + if (isReturning == false) + return false; + + currentLineIndex = returnTarget.lastReadLine; + currentScope = returnTarget; + + isReturning = false; + return true; + } + + public static void setReturnTarget(Scope newReturnTarget){ + isReturning = true; + returnTarget = newReturnTarget; + } + + #endregion + + + } +} + diff --git a/LineParser/Runtime/Commands/BreakAndContinueStatementParser.cs b/LineParser/Runtime/Commands/BreakAndContinueStatementParser.cs new file mode 100644 index 0000000..941cbb0 --- /dev/null +++ b/LineParser/Runtime/Commands/BreakAndContinueStatementParser.cs @@ -0,0 +1,42 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class BreakAndContinueStatementParser + { + public static Logic parseContinueStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + //We use a shallow copy because we alter logicOrder in case of speciall operators + Logic[] cloneLogicOrder = (Logic[])logicOrder.Clone (); + if (cloneLogicOrder.Length != 1 || cloneLogicOrder[0].currentType != WordTypes.continueStatement) + return new UnknownLogic (lineNumber); + + CodeWalker.continueLoop (findParentLoop (currentScope, lineNumber), lineNumber); + return new Variable (); + } + + public static Logic parseBreakStatement(Logic[] logicOrder, int lineNumber, Scope currentScope){ + //We use a shallow copy because we alter logicOrder in case of speciall operators + Logic[] cloneLogicOrder = (Logic[])logicOrder.Clone (); + if (cloneLogicOrder.Length != 1 || cloneLogicOrder[0].currentType != WordTypes.breakStatement) + return new UnknownLogic (lineNumber); + + CodeWalker.breakLoop (findParentLoop (currentScope, lineNumber), lineNumber); + return new Variable (); + } + + + + private static Scope findParentLoop(Scope currentScope, int lineNumber){ + if (currentScope.theScopeType == ScopeType.forLoop || currentScope.theScopeType == ScopeType.whileLoop) + return currentScope; + + if (currentScope.parentScope == null || currentScope.parentScope.theScopeType == ScopeType.function) + ErrorMessage.sendErrorMessage (lineNumber, "Du kan endast använda break i en loop"); + + return findParentLoop (currentScope.parentScope, lineNumber); + } + } +} + diff --git a/LineParser/Runtime/Commands/PureFunctionCallParser.cs b/LineParser/Runtime/Commands/PureFunctionCallParser.cs new file mode 100644 index 0000000..0f9aebf --- /dev/null +++ b/LineParser/Runtime/Commands/PureFunctionCallParser.cs @@ -0,0 +1,32 @@ +using System; +using Compiler; + +namespace Runtime +{ + public class PureFunctionCallParser + { + public static Logic parsePureFunctionCall(Logic[] logicOrder, int lineNumber, Scope currentScope){ + if (logicOrder.Length != 1) + return new UnknownLogic(lineNumber); + + if (logicOrder [0].currentType == WordTypes.functionCall) { + FunctionCall tempCall = (logicOrder [0] as FunctionCall); + FunctionParser.linkFunctionCall (tempCall, lineNumber, currentScope); + + + if (tempCall.targetFunc.pauseWalker) + CodeWalker.pauseWalker (); + + tempCall.runFunction (currentScope); + + if(tempCall.targetFunc.isUserFunction) + throw new FunctionCallException (); + + return tempCall; + } + else + return new UnknownLogic(lineNumber); + } + } +} + diff --git a/LineParser/Runtime/Commands/ReturnStatementCommand.cs b/LineParser/Runtime/Commands/ReturnStatementCommand.cs new file mode 100644 index 0000000..c3313ac --- /dev/null +++ b/LineParser/Runtime/Commands/ReturnStatementCommand.cs @@ -0,0 +1,12 @@ +using System; + +namespace LineParser +{ + public class ReturnStatementCommand + { + public ReturnStatementCommand () + { + } + } +} + diff --git a/LineParser/Runtime/Commands/SpecialVariableDeclare/TextSpeciallVariableDeclare.cs b/LineParser/Runtime/Commands/SpecialVariableDeclare/TextSpeciallVariableDeclare.cs new file mode 100644 index 0000000..98006e1 --- /dev/null +++ b/LineParser/Runtime/Commands/SpecialVariableDeclare/TextSpeciallVariableDeclare.cs @@ -0,0 +1,53 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class TextSpeciallVariableDeclare + { + + + internal static Variable handleTextVariable(Logic[] cloneLogicOrder, int lineNumber, Variable afterEqualSign, Scope currentScope, string variableName){ + Variable returnVar = new Variable(variableName, ""); + string originalStringValue = (cloneLogicOrder [0] as Variable).getString (); + + if (afterEqualSign.variableType == VariableTypes.number) + return handleNumberValue (cloneLogicOrder, returnVar, afterEqualSign, originalStringValue, lineNumber); + + else if (afterEqualSign.variableType == VariableTypes.textString) + return handeTextValue (cloneLogicOrder, returnVar, afterEqualSign, originalStringValue, lineNumber); + + + // ErrorMessage.sendErrorMessage (lineNumber, "Ogiltig använding av extra operatorer"); + return returnVar; + } + + + private static Variable handeTextValue(Logic[] cloneLogicOrder, Variable returnVar, Variable afterEqualSign, string originalStringValue, int lineNumber){ + if (cloneLogicOrder [1].word != "+") + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "När du använder extra operatorer på en text variabel med en annan text kan du endast använda \"+\""); + + returnVar.setValue (originalStringValue + afterEqualSign.getString()); + return returnVar; + } + + + private static Variable handleNumberValue(Logic[] cloneLogicOrder, Variable returnVar, Variable afterEqualSign, string originalStringValue, int lineNumber){ + if (cloneLogicOrder [1].word != "*") + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "När du använder extra operatorer på en text variabel med en siffra kan du endast använda \"*\""); + + if (afterEqualSign.getNumber() % 1 != 0) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Du kan endast multiplicera strängar med heltal"); + + if (afterEqualSign.getNumber() <= 0) + return returnVar; + + for (int i = 0; i < afterEqualSign.getNumber (); i++) + returnVar.setValue (returnVar.getString () + originalStringValue); + + return returnVar; + } + } +} + diff --git a/LineParser/Runtime/Commands/SpeciallVariableDeclareParser.cs b/LineParser/Runtime/Commands/SpeciallVariableDeclareParser.cs new file mode 100644 index 0000000..c7a3f5b --- /dev/null +++ b/LineParser/Runtime/Commands/SpeciallVariableDeclareParser.cs @@ -0,0 +1,56 @@ +using System; +using ErrorHandler; +using Compiler; + +namespace Runtime +{ + public class SpeciallVariableDeclareParser + { + + internal static Variable speciallVariableDeclare(Logic[] cloneLogicOrder, int lineNuber, Variable afterEqualSign, Scope currentScope){ + string variableName = cloneLogicOrder [0].word; + + if (cloneLogicOrder [1].currentType != WordTypes.mathOperator) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNuber, "Extra operator måste vara en matteoperator"); + + int varPos = currentScope.scopeVariables.containsVariable (cloneLogicOrder [0].word); + if(varPos < 0) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNuber, "För att kunna använda extra operatorer måste variabeln med namn \"" + cloneLogicOrder[0].word + "\" redan vara deklarerad "); + cloneLogicOrder [0] = currentScope.scopeVariables.variableList [varPos]; + + if ((cloneLogicOrder [0] as Variable).variableType == VariableTypes.number) + return handleNumberVariable (cloneLogicOrder, lineNuber, afterEqualSign, currentScope); + + if ((cloneLogicOrder [0] as Variable).variableType == VariableTypes.textString) + return TextSpeciallVariableDeclare.handleTextVariable (cloneLogicOrder, lineNuber, afterEqualSign, currentScope, variableName); + + + ErrorHandler.ErrorMessage.sendErrorMessage (lineNuber, "Endast variabler med Nummer eller Text kan använda extra operatorer"); + + return new Variable ("Temp"); + } + + + private static Variable handleNumberVariable(Logic[] cloneLogicOrder, int lineNumber, Variable tempSum, Scope currentScope){ + Logic[] calcSum = new Logic[3]; + calcSum [0] = cloneLogicOrder [0]; + calcSum [1] = cloneLogicOrder [1]; + calcSum [2] = new NumberValue (tempSum.getNumber().ToString()); + Variable tempVar = SumParser.parseIntoSum (calcSum, lineNumber, currentScope); + + tempVar.name = (calcSum [0] as Variable).name; + + return tempVar; + } + + [System.Obsolete("This function should not be in use", true)] + private static Variable getAfterEqualSignSum(Logic[] cloneLogicOrder, int lineNuber, Scope currentScope){ + Logic[] afterEqualSign = InternalParseFunctions.getSubArray(cloneLogicOrder, 3, cloneLogicOrder.Length-1, lineNuber); + + //Debugger.printLogicOrder (afterEqualSign, "Checking how dis turns out"); + return new Variable (); + } + + } +} + diff --git a/LineParser/Runtime/Commands/VariableDeclareParser.cs b/LineParser/Runtime/Commands/VariableDeclareParser.cs new file mode 100644 index 0000000..d7cdf82 --- /dev/null +++ b/LineParser/Runtime/Commands/VariableDeclareParser.cs @@ -0,0 +1,86 @@ +using System; +using System.Linq; +using System.Collections; +using Compiler; + + +namespace Runtime +{ + public class VariableDeclareParser{ + + + public static Logic checkForVariableDecleration(Logic[] logicOrder, int lineNumber, Scope currentScope){ + //We use a shallow copy because we alter logicOrder in case of speciall operators + Logic[] cloneLogicOrder = (Logic[])logicOrder.Clone (); + + if(couldBeVariableDec(cloneLogicOrder, lineNumber) == false) + return new UnknownLogic(lineNumber); + + + Logic[] afterEqualSign = getAfterEqualSign (cloneLogicOrder, lineNumber, currentScope); + if(afterEqualSign == null || afterEqualSign.Length == 0) + return new UnknownLogic(lineNumber); + + Variable afterEqualSignSum = SumParser.parseIntoSum (afterEqualSign, lineNumber, currentScope); + + //Determine whether to use speciallOperators or not + if (cloneLogicOrder [1].currentType != WordTypes.equalSign) + afterEqualSignSum = SpeciallVariableDeclareParser.speciallVariableDeclare (cloneLogicOrder, lineNumber, afterEqualSignSum, currentScope); + else + afterEqualSignSum.name = (cloneLogicOrder[0] as Variable).name; + + //Add the newly declared variable + if (afterEqualSignSum.variableType != VariableTypes.unknown) { + currentScope.scopeVariables.addVariable(afterEqualSignSum, currentScope.scopeParser, lineNumber); + return afterEqualSignSum; + } + + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Något gick fel i variabeldeklareringen"); + return new UnknownLogic(lineNumber); + } + + + + #region Basic Checks + private static bool couldBeVariableDec(Logic[] cloneLogicOrder, int lineNumber){ + if (cloneLogicOrder.Length < 3) + return false; + + if (cloneLogicOrder [0].currentType != WordTypes.variable) + return false; + + return true; + } + #endregion + + + + + #region getLogicAfterEqualSign + private static Logic[] getAfterEqualSign(Logic[] cloneLogicOrder, int lineNumber, Scope currentScope){ + + int equalPos = getEqualPos (cloneLogicOrder); + if ((equalPos != 1 && equalPos != 2)) + return null; + + + Logic[] afterEqualSign = new Logic[cloneLogicOrder.Length - (equalPos+1)]; + for (int i = equalPos+1; i < cloneLogicOrder.Length; i++) + afterEqualSign [i-(equalPos+1)] = cloneLogicOrder [i]; + + return afterEqualSign; + } + + + private static int getEqualPos(Logic[] logicOrder){ + int equalPos = 0; + for (int i = 0; i < logicOrder.Length; i++, equalPos++) + if (logicOrder [i].currentType == WordTypes.equalSign) + break; + + return equalPos; + } + #endregion + } +} + diff --git a/LineParser/Runtime/Debugger.cs b/LineParser/Runtime/Debugger.cs new file mode 100644 index 0000000..0888e57 --- /dev/null +++ b/LineParser/Runtime/Debugger.cs @@ -0,0 +1,34 @@ +using System; +using Compiler; + +namespace Runtime +{ + public class Debugger + { + + public static void printLogicOrder(Logic[] logicOrder, string message){ + Print.print (message + "************"); + foreach (Logic l in logicOrder) + Print.print (l.currentType.ToString ()); + Print.print ("*********************"); + } + + public static void printStackTrace(Scope currentScope){ + string stackString = ""; + + Scope tempScope = currentScope; + while (tempScope != null) { + if (tempScope.theScopeType == ScopeType.main || tempScope.theScopeType == ScopeType.function) + stackString += tempScope.theScopeType.ToString () + " - "; + + tempScope = tempScope.parentScope; + } + + Print.print ("Stack trace: ******"); + Print.print (stackString); + Print.print ("**********"); + } + + } +} + diff --git a/LineParser/Runtime/Print.cs b/LineParser/Runtime/Print.cs new file mode 100644 index 0000000..37da22f --- /dev/null +++ b/LineParser/Runtime/Print.cs @@ -0,0 +1,14 @@ +using System; + +namespace Runtime +{ + public class Print + { + public static Action printFunction; + + internal static void print(string message){ + printFunction.Invoke (message); + } + } +} + diff --git a/LineParser/Runtime/Stack/ReturnMemoryClear.cs b/LineParser/Runtime/Stack/ReturnMemoryClear.cs new file mode 100644 index 0000000..1a9d983 --- /dev/null +++ b/LineParser/Runtime/Stack/ReturnMemoryClear.cs @@ -0,0 +1,39 @@ +using System; + +namespace Compiler +{ + public class ReturnMemoryClear + { + public static void clearLineMemory(CodeLine currentLine){ + searchLogicOrder(currentLine.getLatestOrder()); + currentLine.resetCalculations (); + } + + private static void searchLogicOrder(Logic[] logicOrder){ + foreach (Logic l in logicOrder) + if (l.currentType == WordTypes.package) + clearPackageMemory (l as Package); + else if(l.currentType == WordTypes.functionCall) + clearFuncCallMemory (l as FunctionCall); + } + + + private static void clearPackageMemory(Package thePackage){ + searchLogicOrder(thePackage.getLatestOrder()); + thePackage.resetCalculations (); + } + + + private static void clearFuncCallMemory(FunctionCall theFuncCall){ + if (theFuncCall.returnCalculations == null) + return; + + foreach(Logic[] l in theFuncCall.returnCalculations) + searchLogicOrder(l); + + theFuncCall.resetCalculations (); + } + + } +} + diff --git a/LineParser/Runtime/Stack/ReturnMemoryControll.cs b/LineParser/Runtime/Stack/ReturnMemoryControll.cs new file mode 100644 index 0000000..b1efeaf --- /dev/null +++ b/LineParser/Runtime/Stack/ReturnMemoryControll.cs @@ -0,0 +1,135 @@ +using System; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + public class ReturnMemoryControll + { + public static void insertReturnExpectation(CodeLine currentLine, int lineNumber, Logic targetLogic){ + if (currentLine.returnCalculations == null) + currentLine.returnCalculations = (Logic[])currentLine.logicOrder.Clone (); + + Logic[] tempOrder = (Logic[])currentLine.getLatestOrder(); + + searchInLogicOrderExpect (tempOrder, lineNumber, targetLogic); + } + + + private static bool searchInLogicOrderExpect(Logic[] logicOrder, int lineNumber, Logic targetLogic){ + for (int i = 0; i < logicOrder.Length; i++) + if (logicOrder [i] == targetLogic) { + logicOrder [i] = new ReturnValue(); + + return true; + } + else if (logicOrder [i].currentType == WordTypes.package) { + if (insertReturnValueIntoPackageExpect (logicOrder[i] as Package, lineNumber, targetLogic)) + return true; + } + else if (logicOrder [i].currentType == WordTypes.functionCall) { + if (insertReturnValueIntoFuncCallExpect (logicOrder[i] as FunctionCall, lineNumber, targetLogic)) + return true; + } + + return false; + } + + + + private static bool insertReturnValueIntoPackageExpect(Package thePackage, int lineNumber, Logic targetLogic){ + if (thePackage.returnCalculations == null) + thePackage.returnCalculations = (Logic[])thePackage.logicOrder.Clone (); + + Logic[] tempOrder = thePackage.getLatestOrder(); + return searchInLogicOrderExpect (tempOrder, lineNumber, targetLogic); + } + + + + + private static bool insertReturnValueIntoFuncCallExpect(FunctionCall theFuncCall, int lineNumber, Logic targetLogic){ + if (theFuncCall.returnCalculations == null) + return false; + + + foreach (Logic[] l in theFuncCall.returnCalculations) { + if (searchInLogicOrderExpect (l, lineNumber, targetLogic)) + return true; + } + + return false; + } + + + + + + //********************************** + + public static void insertReturnValue(CodeLine currentLine, int lineNumber, Variable returnVar){ + Logic[] tempOrder = currentLine.getLatestOrder(); + + // Debugger.printLogicOrder (tempOrder, "Return insert Order"); + + searchInLogicOrder (tempOrder, lineNumber, returnVar); + } + + + private static bool searchInLogicOrder(Logic[] logicOrder, int lineNumber, Variable returnVar){ + + for (int i = 0; i < logicOrder.Length; i++) + if (logicOrder [i].currentType == WordTypes.returnValue) { + // Debugger.printLogicOrder (logicOrder, "Pre Order"); + logicOrder[i] = insertTheValue (returnVar); + // Debugger.printLogicOrder (logicOrder, "Post Order"); + return true; + } + else if (logicOrder [i].currentType == WordTypes.package) { + if (insertReturnValueIntoPackage (logicOrder[i] as Package, lineNumber, returnVar)) + return true; + } + else if (logicOrder [i].currentType == WordTypes.functionCall) { + if (insertReturnValueIntoFuncCall (logicOrder[i] as FunctionCall, lineNumber, returnVar)) + return true; + } + + return false; + } + + + + private static bool insertReturnValueIntoPackage(Package thePackage, int lineNumber, Variable returnVar){ + Logic[] tempOrder = thePackage.getLatestOrder(); + return searchInLogicOrder (tempOrder, lineNumber, returnVar); + } + + private static bool insertReturnValueIntoFuncCall(FunctionCall theFuncCall, int lineNumber, Variable returnVar){ + if (theFuncCall.returnCalculations == null) + return false; + + foreach (Logic[] l in theFuncCall.returnCalculations) + if (searchInLogicOrder (l, lineNumber, returnVar)) { + return true; + } + + return false; + } + + + private static Logic insertTheValue(Variable returnVar){ + Print.print ("Var type: " + returnVar.variableType); + + if (returnVar.variableType == VariableTypes.boolean) + return new BooleanValue (returnVar.getBool ()); + else if (returnVar.variableType == VariableTypes.number) + return new NumberValue (returnVar.getNumber ()); + else if (returnVar.variableType == VariableTypes.textString) + return new TextValue (returnVar.getString ()); + + return new Variable ("Nill"); + } + + } +} + diff --git a/LineParser/Runtime/VariableWindow/VariableWindow.cs b/LineParser/Runtime/VariableWindow/VariableWindow.cs new file mode 100644 index 0000000..91f07b9 --- /dev/null +++ b/LineParser/Runtime/VariableWindow/VariableWindow.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Compiler; + +namespace Runtime +{ + public class VariableWindow + { + + private static Action insertVariable; + private static Action resetList; + + private static List tempVariables = new List(); + + public static void setVariableWindowFunctions(Action insertVariableToList, Action resetTheList){ + insertVariable = insertVariableToList; + resetList = resetTheList; + } + + internal static void sendStackVariables(Scope currentScope){ + resetList.Invoke (); + tempVariables.Clear (); + tempVariables.Add (new Variables ()); + sendScopeVariables (currentScope); + + foreach (Variables Vars in tempVariables) + { + foreach (Variable v in Vars.variableList) + { + //Print.print("Variable to send: " + v.name); + insertVariable(v); + } + } + } + + private static void sendScopeVariables(Scope currentScope){ + Variables latestList = tempVariables [tempVariables.Count - 1]; + foreach (Variable v in currentScope.scopeVariables.variableList) + if (latestList.containsVariable (v.name) < 0) + latestList.addVariable (v, currentScope.scopeParser, 0); + + + + /* + if (tempVariables == null) + tempVariables = new Variables (); + + foreach (Variable v in currentScope.scopeVariables.variableList) + tempVariables.addVariable (v, Compiler.SyntaxCheck.globalParser, 0); + + + if (currentScope.theScopeType == ScopeType.main || currentScope.theScopeType == ScopeType.function) { + for (int i = tempVariables.variableList.Count - 1; i >= 0; i--) + insertVariable (tempVariables.variableList [i]); + tempVariables = null; + } + */ + if (currentScope.parentScope != null) { + if (currentScope.theScopeType == ScopeType.function) + tempVariables.Add (new Variables ()); + sendScopeVariables (currentScope.parentScope); + } + } + + } +} + diff --git a/LineParser/Scope/Parser/IndentParser.cs b/LineParser/Scope/Parser/IndentParser.cs new file mode 100644 index 0000000..2bd9305 --- /dev/null +++ b/LineParser/Scope/Parser/IndentParser.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using ErrorHandler; + +namespace Compiler +{ + public class IndentParser + { + public static Scope parseIntoScopes(List programLines){ + + Scope mainScope = parseCurrentScope (0, 0, programLines, true); + + return mainScope; + } + + + static Scope parseCurrentScope(int indentLevel, int startNumber, List programLines, bool isMain){ + List scopeLines = new List (); + List childScopes = new List (); + ScopeType currentScopeType; + + //Set current Scope Type + if (!isMain) { + if (startNumber > 0) { + scopeLines.Add (programLines [startNumber - 1]); + currentScopeType = getNonMainScopeType (programLines [startNumber - 1].words, programLines [startNumber - 1].lineNumber); + } + else + currentScopeType = ScopeType.unknown; + } + else + currentScopeType = ScopeType.main; + + + int lastLine = startNumber; + for (int i = startNumber; i < programLines.Count; i++) { + int currentIndent = programLines [i].indentLevel; + + if (currentIndent == indentLevel) { + lastLine = i; + scopeLines.Add(programLines[i]); + } + else if (currentIndent < indentLevel) + return new Scope (currentScopeType, startNumber, lastLine, indentLevel, scopeLines, childScopes, false); + + else if (currentIndent > indentLevel) { + Scope childScope = parseCurrentScope (currentIndent, i, programLines, false); + i = childScope.endLine; + childScopes.Add (childScope); + + if (i != programLines.Count - 1) + if (programLines [i + 1].indentLevel < indentLevel) + lastLine = i; + } + + if (i == programLines.Count - 1) { + + if (childScopes.Count > 0) { + int childLastValue = childScopes [childScopes.Count - 1].endLine; + if (childLastValue > lastLine) + lastLine = childLastValue; + } + return new Scope (currentScopeType, startNumber, lastLine, indentLevel, scopeLines, childScopes, false); + } + + } + + return new Scope (currentScopeType, startNumber, lastLine, indentLevel, scopeLines, childScopes, false); + } + + + + + static ScopeType getNonMainScopeType(string[] words, int lineNumber){ + + ScopeType tempType = ScopeType.unknown; + if (words [0].StartsWith("for")) + tempType = ScopeType.forLoop; + else if (words [0].StartsWith("while")) + tempType = ScopeType.whileLoop; + else if (words [0].StartsWith("def")) + tempType = ScopeType.function; + else if (words [0].StartsWith("if")) + tempType = ScopeType.ifStatement; + else if (words [0].StartsWith("else")) + tempType = ScopeType.elseStatement; + else if (words [0].StartsWith("elif")) + tempType = ScopeType.elifStatement; + + if (tempType == ScopeType.unknown) { + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, ErrorHandler.ErrorType.Indentation, IndentationErrorType.unknownIndentStarter.ToString(), null); + return tempType; + } + + return tempType; + } + + + + static bool scopeCheck(Scope currentScope){ + + foreach (Scope tempScope in currentScope.childScopes) + if (!scopeCheck (tempScope)) + return false; + + if (currentScope.theScopeType == ScopeType.unknown) + return false; + + + return true; + } + + } +} + diff --git a/LineParser/Scope/Parser/ScopeLogicParser.cs b/LineParser/Scope/Parser/ScopeLogicParser.cs new file mode 100644 index 0000000..1c45c36 --- /dev/null +++ b/LineParser/Scope/Parser/ScopeLogicParser.cs @@ -0,0 +1,28 @@ +using System; + +namespace Compiler +{ + public class ScopeLogicParser + { + + public static void parseScopeLineLogic(Scope currentScope){ + if (currentScope.childScopes.Count == 0) { + parseCodeLineLogic (currentScope); + return; + } + else + foreach (Scope tempScope in currentScope.childScopes) + parseScopeLineLogic (tempScope); + + + parseCodeLineLogic (currentScope); + } + + static void parseCodeLineLogic(Scope currentScope){ + foreach (CodeLine tempLine in currentScope.codeLines) + tempLine.logicOrder = WordsToLogicParser.determineLogicFromWords (tempLine.words, tempLine.lineNumber, currentScope); + } + + } +} + diff --git a/LineParser/Scope/Parser/ScopeParser.cs b/LineParser/Scope/Parser/ScopeParser.cs new file mode 100644 index 0000000..2ed46b9 --- /dev/null +++ b/LineParser/Scope/Parser/ScopeParser.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using SyntaxCheck; + +namespace Compiler +{ + public class ScopeParser + { + /// + /// Parses all text into lines and lines into words. Parses the into scopes. Checks syntax for indentation, scopeStarters + /// + /// The into scopes. + /// Code text. + public static Scope parseIntoScopes(string codeText){ + + // Creates list with CodeLine objects with lineNumber, indentNumber and word list + List programLines = SyntaxCheck.parseLines(codeText); + + Scope mainScope = IndentParser.parseIntoScopes (programLines); + ScopeLogicParser.parseScopeLineLogic (mainScope); + ScopeStarterParser.checkScopeStarters (programLines, mainScope); + //CodeSyntaxWalker.walkAllLines (programLines.ToArray (), mainScope); + + return mainScope; + } + + + } +} + diff --git a/LineParser/Scope/Parser/ScopeReturnParser.cs b/LineParser/Scope/Parser/ScopeReturnParser.cs new file mode 100644 index 0000000..f9bea70 --- /dev/null +++ b/LineParser/Scope/Parser/ScopeReturnParser.cs @@ -0,0 +1,29 @@ +using System; +using Runtime; +using ErrorHandler; + +namespace Compiler +{ + public class ScopeReturnParser + { + public static void parseScopeReturns(Scope currentSuperParent, Scope currentScope){ + checkLinesInScope (currentSuperParent, currentScope); + + foreach (Scope s in currentScope.childScopes) + parseScopeReturns (currentSuperParent, s); + } + + private static void checkLinesInScope(Scope currentSuperParent, Scope currentScope){ + foreach (CodeLine c in currentScope.codeLines) + if (c.logicOrder [0].currentType == WordTypes.returnStatement) { + if (currentSuperParent.theScopeType != ScopeType.function) + ErrorMessage.sendErrorMessage (c.lineNumber, "Du kan bara returnera värden ifrån en funktion " + currentSuperParent.theScopeType); + + + (c.logicOrder [0] as ReturnStatement).FunctionParent = currentSuperParent; + } + + } + } +} + diff --git a/LineParser/Scope/Parser/ScopeStarterParser.cs b/LineParser/Scope/Parser/ScopeStarterParser.cs new file mode 100644 index 0000000..4b41429 --- /dev/null +++ b/LineParser/Scope/Parser/ScopeStarterParser.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using ErrorHandler; +using Runtime; + +namespace Compiler +{ + + public class ScopeStarterParser{ + + public static void checkScopeStarters(List programLines, Scope mainScope){ + + int expectedIndent = 0; + bool expectedHigherIndent = true; + bool isFirst = true; + + for (int i = 0; i < programLines.Count; i++) { + if (expectedHigherIndent) { + if (isFirst) { + if (programLines [i].indentLevel != 0) + ErrorMessage.sendErrorMessage (programLines [i].lineNumber, ErrorType.Indentation, IndentationErrorType.firstLineIndentError.ToString(), null); + isFirst = false; + } else { + if (programLines [i].indentLevel != expectedIndent) + ErrorMessage.sendErrorMessage (programLines [i].lineNumber, ErrorType.Indentation, IndentationErrorType.indentationError.ToString(), null); + } + } + + if (SpecialWordParser.isValidScopeStarter (programLines [i].logicOrder, programLines [i].lineNumber)) { + expectedIndent = programLines [i].indentLevel + 1; + expectedHigherIndent = true; + + if (i == programLines.Count - 1) + ErrorMessage.sendErrorMessage (programLines [i].lineNumber, ErrorType.Indentation, IndentationErrorType.expectingBodyAfterScopeStarter.ToString(), null); + } + else + expectedHigherIndent = false; + } + + setScopeStarterTargets (mainScope); + } + + static void setScopeStarterTargets(Scope currentScope){ + int currentChildScope = 0; + int linkCounter = 0; + + for(int i = 0; i < currentScope.codeLines.Count; i++){ + CodeLine line = currentScope.codeLines [i]; + + if (SpecialWordParser.isValidScopeStarter (line.logicOrder, line.lineNumber)) { + if (currentChildScope > currentScope.childScopes.Count - 1) + ErrorMessage.sendErrorMessage (line.lineNumber, ErrorType.System, SystemFailureErrorType.scopeParsingMalfunction.ToString(), null); + + (line.logicOrder [0] as ScopeStarter).setTargetScope(currentScope.childScopes [currentChildScope]); + currentChildScope++; + + + // Links else/elif + if (line.logicOrder [0] is ComparisonScope) { + if (i == 0 && line.logicOrder [0] is IfStatement == false) + ErrorMessage.sendErrorMessage (line.lineNumber , ErrorType.ElseStatements, ElseErrorType.missingIfBeforeElse.ToString(), null); + + if (line.logicOrder [0] is IfStatement == false) + linkElseStatement (line.logicOrder [0], currentScope.codeLines [i - 1].logicOrder [0], currentScope, linkCounter, line.lineNumber); + + + linkCounter++; + } else + linkCounter = 0; + } + + + } + + foreach (Scope tempScope in currentScope.childScopes) + setScopeStarterTargets (tempScope); + + } + + static void linkElseStatement(Logic newStatement, Logic preLineLogic, Scope currentScope, int linkCounter, int lineNumber){ + if (linkCounter == 0) + ErrorMessage.sendErrorMessage (lineNumber , ErrorType.ElseStatements, ElseErrorType.missingIfBeforeElse.ToString(), null); + if(preLineLogic is ElseStatement) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.ElseStatements, ElseErrorType.elseCantLinkToElse.ToString(), null); + + (preLineLogic as ComparisonScope).linkNextStatement (newStatement as ComparisonScope); + } + + + } + +} + diff --git a/LineParser/Scope/Scope.cs b/LineParser/Scope/Scope.cs new file mode 100644 index 0000000..5d7eabb --- /dev/null +++ b/LineParser/Scope/Scope.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using B83.ExpressionParser; +using Runtime; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +namespace Compiler +{ + + public class Scope + { + public ScopeType theScopeType; + public ScopeLoop theScoopLoop; + + public int indentLevel = 0; + public int startLine, endLine; + public bool isReturning = false; + + public List codeLines; + public List childScopes; + private Scope secretParent; + public Scope parentScope{ + get{ + return secretParent; + } + set{ + secretParent = value; + } + } + + public CurrentFunctions scopeFunctions; + public Variables scopeVariables; + public ExpressionParser scopeParser; + public int lastReadLine = 0; + + + public Scope(ScopeType theScopeType, int startLine, int endLine, int indentLevel, List codeLines, List childScopes, bool isClone){ + scopeParser = new ExpressionParser (); + + this.theScopeType = theScopeType; + this.startLine = startLine; + this.endLine = endLine; + this.indentLevel = indentLevel; + + this.codeLines = codeLines; + this.childScopes = childScopes; + + scopeVariables = new Variables (); + scopeFunctions = new CurrentFunctions (); + scopeParser = new ExpressionParser (); + + if (theScopeType == ScopeType.main || isClone) + theScopeType = ScopeType.main; + else + this.codeLines.RemoveAt (0); + } + + public void giveInheritVariables(List inheritVariables){ + foreach (Variable var in inheritVariables) { + + int varPos = scopeVariables.containsVariable (var.name); + if (varPos >= 0) { + if (scopeVariables.variableList [varPos].isForLoopVariable) { + double value = scopeVariables.variableList [varPos].getNumber(); + scopeVariables.addVariable (var, scopeParser, -1); + scopeVariables.variableList [varPos].setValue (value); + } + else + scopeVariables.addVariable (var, scopeParser, codeLines[0].lineNumber); + } + else + scopeVariables.addVariable (var, scopeParser, codeLines[0].lineNumber); + + } + + } + + public void upInheritVariable(Scope targetScope){ + foreach (Variable v in scopeVariables.variableList) + targetScope.scopeVariables.addVariable (v, scopeParser, codeLines [0].lineNumber); + } + + public CodeLine getCurrentLine(){ + return codeLines [lastReadLine]; + } + + public void setCurrentLine(CodeLine newLine) + { + codeLines[lastReadLine] = newLine; + } + + + //Not working ish.... + public Scope createDeepCopy(){ + + List tempCodeLines = new List (); + foreach (CodeLine c in codeLines) + tempCodeLines.Add (c.cloneLine ()); + + List tempChildScopes = new List (); + foreach (Scope s in childScopes) + tempChildScopes.Add (s.createDeepCopy()); + + Scope tempScope = new Scope (theScopeType, startLine, endLine, indentLevel, tempCodeLines, tempChildScopes, true); + + + return tempScope; + } + + + public void linkChildScopes(Scope currentScope){ + int counter = 0; + foreach (CodeLine c in currentScope.codeLines) { + + if (c.logicOrder [0] is ScopeStarter) { + (c.logicOrder [0] as ScopeStarter).setTargetScope(currentScope.childScopes [counter]); + counter++; + } + } + + foreach (Scope s in currentScope.childScopes) + linkChildScopes (s); + } + } +} + diff --git a/LineParser/Scope/ScopeLoop.cs b/LineParser/Scope/ScopeLoop.cs new file mode 100644 index 0000000..5f622fb --- /dev/null +++ b/LineParser/Scope/ScopeLoop.cs @@ -0,0 +1,14 @@ +using System; + +namespace Compiler +{ + + public class ScopeLoop : ScopeStarter { + + public ComparisonType theComparisonType; + public Variable leftValue; + public Variable rightValue; + + } +} + diff --git a/LineParser/Scope/ScopeStarter.cs b/LineParser/Scope/ScopeStarter.cs new file mode 100644 index 0000000..79b968c --- /dev/null +++ b/LineParser/Scope/ScopeStarter.cs @@ -0,0 +1,22 @@ +using System; +using Runtime; + +namespace Compiler +{ + public abstract class ScopeStarter : Logic { + + private Scope targetScope; + public bool doEnterScope; + public bool doParseLine = true; + + + public void setTargetScope(Scope targetScope){ + this.targetScope = targetScope; + } + + public Scope getTargetScope(){ + return targetScope; + } + } +} + diff --git a/LineParser/Scope/ScopeType.cs b/LineParser/Scope/ScopeType.cs new file mode 100644 index 0000000..a2bec3c --- /dev/null +++ b/LineParser/Scope/ScopeType.cs @@ -0,0 +1,16 @@ +using System; + +namespace Compiler{ + + + public enum ScopeType{ + function, + forLoop, + whileLoop, + ifStatement, + elseStatement, + elifStatement, + main, + unknown + } +} \ No newline at end of file diff --git a/LineParser/SyntaxCheck.cs b/LineParser/SyntaxCheck.cs new file mode 100644 index 0000000..3a06be1 --- /dev/null +++ b/LineParser/SyntaxCheck.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using B83; + +namespace Compiler +{ + public class SyntaxCheck + { + + public static B83.ExpressionParser.ExpressionParser globalParser; + + /// + /// Declares globalParser and returns parsed lines in list of Codelines. + /// + public static List parseLines(string currentText){ + globalParser = new B83.ExpressionParser.ExpressionParser (); + + List textLines = LineSplitter.splitTextIntoLines(currentText); + return LineParser.parseLines (textLines); + + } + + /// Links fullText and actions (endWalker etc) to CodeWalker via setActions. + public static void CompileCode(string fullText, Action endWalker, Action pauseWalker, Action, Scope> linkSubmitInput, Action activateFunctionColor, Action setWalkerPos){ + Scope mainScope = ScopeParser.parseIntoScopes (fullText); + Runtime.CodeWalker.setActions(endWalker, pauseWalker, linkSubmitInput, activateFunctionColor, setWalkerPos, mainScope); + } + } +} + diff --git a/LineParser/SyntaxCheck/CodeSyntaxWalker.cs b/LineParser/SyntaxCheck/CodeSyntaxWalker.cs new file mode 100644 index 0000000..e20ba33 --- /dev/null +++ b/LineParser/SyntaxCheck/CodeSyntaxWalker.cs @@ -0,0 +1,33 @@ +using ErrorHandler; +using System.Collections; +using Compiler; +using Runtime; + +namespace SyntaxCheck{ + + internal class CodeSyntaxWalker{ + + private static void findCommandType(CodeLine c, Scope mainScope){ + checkForUnknown (c.logicOrder, c.lineNumber); + + if (PossibleVariableDeclare.checkForVariableDecleration (c.logicOrder, c.lineNumber)) + return; + + if (PossibleSpeciallWord.checkForSpeciallWord (c.logicOrder, c.lineNumber, mainScope)) + return; + + if (PossibleFunctionCall.possibleFunctionCall (c.logicOrder, c.lineNumber)) + return; + + ErrorMessage.sendErrorMessage (c.lineNumber, ErrorType.System, SystemFailureErrorType.unknownLogic.ToString(), new string[]{"0"}); + } + + static void checkForUnknown(Logic[] logicOrder, int lineNumber){ + foreach (Logic L in logicOrder) + if (L.currentType == WordTypes.unknown) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.unknownLogic.ToString(), new string[]{"1"}); + } + } + + +} \ No newline at end of file diff --git a/LineParser/SyntaxCheck/PossibleFunctionCall.cs b/LineParser/SyntaxCheck/PossibleFunctionCall.cs new file mode 100644 index 0000000..73fc34e --- /dev/null +++ b/LineParser/SyntaxCheck/PossibleFunctionCall.cs @@ -0,0 +1,16 @@ +using System.Collections; +using Compiler; + +namespace SyntaxCheck{ + + internal class PossibleFunctionCall { + + public static bool possibleFunctionCall(Logic[] logicOrder, int lineNumber){ + if (logicOrder.Length == 1 && logicOrder [0].currentType == WordTypes.functionCall) + return true; + + return false; + } + } + +} \ No newline at end of file diff --git a/LineParser/SyntaxCheck/PossibleSpeciallWord.cs b/LineParser/SyntaxCheck/PossibleSpeciallWord.cs new file mode 100644 index 0000000..07a11a4 --- /dev/null +++ b/LineParser/SyntaxCheck/PossibleSpeciallWord.cs @@ -0,0 +1,135 @@ +using ErrorHandler; +using System.Collections; +using Compiler; + +namespace SyntaxCheck{ + + internal class PossibleSpeciallWord{ + + public static bool checkForSpeciallWord(Logic[] logicOrder, int lineNumber, Scope mainScope){ + switch (logicOrder[0].currentType) { + + case WordTypes.ifOperator: + return ifCheck (logicOrder, lineNumber); + case WordTypes.elseOperator: + return elseCheck(logicOrder, lineNumber); + + case WordTypes.forLoop: + return forCheck(logicOrder, lineNumber, mainScope); + + case WordTypes.whileLoop: + return whileCheck (logicOrder, lineNumber); + + case WordTypes.defStatement: + return defCheck (logicOrder, lineNumber); + + case WordTypes.returnStatement: + return returnCheck (logicOrder, lineNumber); + + default: + return false; + } + + } + + private static bool returnCheck(Logic[] logicOrder, int lineNumber){ + if (logicOrder.Length < 2) + ErrorMessage.sendErrorMessage (lineNumber, "Du måste returnera något"); + + ValidSumCheck.checkIfValidSum ((InternalParseFunctions.getSubArray(logicOrder, 1, logicOrder.Length-1, lineNumber)), lineNumber); + + + return true; + } + + + private static bool ifCheck(Logic[] logicOrder, int lineNumber){ + if (logicOrder [logicOrder.Length - 1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.IfStatements, IfErrorType.missingIndentOperator.ToString(), null); + + if (logicOrder.Length < 3) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.IfStatements, IfErrorType.unknownFormat.ToString(), null); + + + Logic[] statementLogic = new Logic[logicOrder.Length - 2]; + + for (int i = 1; i < logicOrder.Length - 1; i++) + statementLogic [i - 1] = logicOrder [i]; + + if(!PossibleStatement.validStatement(statementLogic, lineNumber)) + ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.possibleComparissonStatements.ToString(), null); + + return true; + } + + + private static bool elseCheck(Logic[] logicOrder, int lineNumber){ + if (logicOrder.Length != 2) + ErrorMessage.sendErrorMessage (lineNumber, "Okänkt format på din Else sats"); + + if (logicOrder [logicOrder.Length - 1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Det saknas ett \":\" i slutet av din Else"); + + return true; + } + + private static bool forCheck(Logic[] logicOrder, int lineNumber, Scope currentScope){ + if (logicOrder.Length != 5) + ErrorMessage.sendErrorMessage (lineNumber, "Okänt format på din for loop"); + + if (logicOrder [1].currentType != WordTypes.variable) + ErrorMessage.sendErrorMessage (lineNumber, "Förväntade sig en variabel som 2:a ord"); + + if (logicOrder[2].word != "in") + ErrorMessage.sendErrorMessage (lineNumber, "Förväntade sig ordet \"in\" 3:e ord"); + + if (logicOrder [3].currentType != WordTypes.functionCall) + ErrorMessage.sendErrorMessage (lineNumber, "Förväntade sig funktionsanrop till \"range\" som 4:e ord"); + + FunctionParser.linkFunctionCall ((logicOrder [3] as FunctionCall), lineNumber, currentScope); + if ((logicOrder [3] as FunctionCall).targetFunc.name != "range") + ErrorMessage.sendErrorMessage (lineNumber, "Förväntade sig funktionsanrop till \"range\" som 4:e ord"); + + if (logicOrder [4].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Saknas ett \":\" i slutet av din for loop"); + + + return true; + } + + private static bool whileCheck(Logic[] logicOrder, int lineNumber){ + if (logicOrder.Length < 3) + ErrorMessage.sendErrorMessage (lineNumber, "Okänt format i din While loop"); + + if (logicOrder [logicOrder.Length -1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Saknas ett \":\" i slutet av din While loop"); + + + Logic[] statementLogic = new Logic[logicOrder.Length - 2]; + for (int i = 1; i < logicOrder.Length - 1; i++) + statementLogic [i - 1] = logicOrder [i]; + + + if(!PossibleStatement.validStatement(statementLogic, lineNumber)) + ErrorMessage.sendErrorMessage (lineNumber, "Okänt format i din While loops expression"); + + + return true; + } + + + private static bool defCheck(Logic[] logicOrder, int lineNumber){ + if (logicOrder.Length != 3) + ErrorMessage.sendErrorMessage (lineNumber, "Okänt format i din funktions definiering"); + + if (logicOrder [logicOrder.Length -1].currentType != WordTypes.indentOperator) + ErrorMessage.sendErrorMessage (lineNumber, "Saknas ett \":\" i slutet av din funktions definiering"); + + if (logicOrder [1].currentType != WordTypes.functionCall) + ErrorMessage.sendErrorMessage (lineNumber, "Funktionsnamnet går av någon anledning inte att använda"); + + return true; + } + } + +} \ No newline at end of file diff --git a/LineParser/SyntaxCheck/PossibleStatement.cs b/LineParser/SyntaxCheck/PossibleStatement.cs new file mode 100644 index 0000000..e45f403 --- /dev/null +++ b/LineParser/SyntaxCheck/PossibleStatement.cs @@ -0,0 +1,108 @@ +using ErrorHandler; +using System.Collections.Generic; +using System; +using Compiler; + +public class PossibleStatement{ + + internal static bool validStatement(Logic[] logicOrder, int lineNumber){ + List statementParts = new List (); + + int lastOperatorPos = -1; + for (int i = 0; i < logicOrder.Length; i++) + if (logicOrder [i].currentType == WordTypes.andOperator || logicOrder [i].currentType == WordTypes.orOperator) { + statementParts.Add(InternalParseFunctions.getSubArray(logicOrder,lastOperatorPos+1, i-1, lineNumber)); + lastOperatorPos = i; + } + + statementParts.Add (InternalParseFunctions.getSubArray (logicOrder, lastOperatorPos + 1, logicOrder.Length-1, lineNumber)); + + + List partStatementValues = new List (); + foreach (Logic[] l in statementParts) + if (validPartStatement (l, lineNumber) != true) + return false; + + + + return true; + } + + + + internal static bool validPartStatement(Logic[] logicOrder, int lineNumber){ + #region findOperators + int operatorLow = 0; + int operatorHigh = 0; + int operatorAmount = 0; + for (int i = 0; i < logicOrder.Length; i++) + if (isStatementOperator (logicOrder [i])) { + if (operatorLow == 0) + operatorLow = i; + else + operatorHigh = i; + operatorAmount++; + } + + #endregion + + if (operatorAmount > 2) + ErrorMessage.sendErrorMessage (lineNumber, "Operatorerna i ditt expression går inte att tyda"); + if (operatorAmount == 0) + return true; + + if (operatorAmount == 2) { + if (operatorHigh - operatorLow != 1) + ErrorMessage.sendErrorMessage (lineNumber, "Operatorerna måste komma efter varandra"); + + } + else + operatorHigh = operatorLow; + + + + + Logic[] leftSide = new Logic[operatorLow]; + Logic[] rightSide = new Logic[logicOrder.Length - 1 - operatorHigh]; + Logic[] operators = new Logic[operatorAmount]; + + setSidesOfStatement (logicOrder, leftSide, rightSide, operators, operatorLow, operatorHigh); + + ComparisonType operatorType = ComparisonOperatorParser.parseOperators (operators); + + if (operatorType == ComparisonType.unknown) + ErrorMessage.sendErrorMessage (lineNumber, "Operatorerna går inte att tyda"); + + ValidSumCheck.checkIfValidSum (leftSide, lineNumber); + ValidSumCheck.checkIfValidSum (rightSide, lineNumber); + + return true; + } + + static void setSidesOfStatement(Logic[] logicOrder, Logic[] leftSide, Logic[] rightSide, Logic[] operators, int operatorLow, int operatorHigh){ + + for (int i = 0; i < leftSide.Length; i++) + leftSide [i] = logicOrder [i]; + + for (int i = operatorHigh+1; i < logicOrder.Length; i++) + rightSide [i - (operatorHigh+1)] = logicOrder [i]; + + for (int i = operatorLow; i <= operatorHigh; i++) + operators [i - operatorLow] = logicOrder [i]; + } + + public static bool isStatementOperator(Logic currentLogic){ + if (currentLogic.currentType == WordTypes.equalSign) + return true; + + if (currentLogic.currentType == WordTypes.lessThenSign || currentLogic.currentType == WordTypes.greaterThenSign) + return true; + + if (currentLogic.currentType == WordTypes.xorOperator) + return true; + + return false; + } + + +} diff --git a/LineParser/SyntaxCheck/PossibleVariableDeclare.cs b/LineParser/SyntaxCheck/PossibleVariableDeclare.cs new file mode 100644 index 0000000..451e876 --- /dev/null +++ b/LineParser/SyntaxCheck/PossibleVariableDeclare.cs @@ -0,0 +1,35 @@ +using System.Collections; +using Runtime; +using Compiler; + +public class PossibleVariableDeclare{ + + internal static bool checkForVariableDecleration(Logic[] logicOrder, int lineNumber){ + + if (logicOrder.Length < 3) + return false; + + if (logicOrder [0].currentType != WordTypes.variable) + return false; + + int equalPos = 0; + for (int i = 0; i < logicOrder.Length; i++, equalPos++) + if (logicOrder [i].currentType == WordTypes.equalSign) + break; + + if (equalPos != 1 && equalPos != 2) + return false; + + if (equalPos == 2 && logicOrder [1].currentType != WordTypes.mathOperator) + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, "Du kan bara ha matte operatorer i special deklareringar!"); + + Logic[] afterEqualSign = new Logic[logicOrder.Length - (equalPos+1)]; + for (int i = equalPos+1; i < logicOrder.Length; i++) + afterEqualSign [i-(equalPos+1)] = logicOrder [i]; + + + ValidSumCheck.checkIfValidSum (afterEqualSign, lineNumber); + + return true; + } +} diff --git a/LineParser/Tags/Logic/BoolType.cs b/LineParser/Tags/Logic/BoolType.cs new file mode 100644 index 0000000..5d43ae9 --- /dev/null +++ b/LineParser/Tags/Logic/BoolType.cs @@ -0,0 +1,9 @@ +using System; + +namespace Compiler +{ + public interface BoolType + { + } +} + diff --git a/LineParser/Tags/Logic/ComparisonScope.cs b/LineParser/Tags/Logic/ComparisonScope.cs new file mode 100644 index 0000000..f2e30eb --- /dev/null +++ b/LineParser/Tags/Logic/ComparisonScope.cs @@ -0,0 +1,13 @@ +using System; + +namespace Compiler +{ + public interface ComparisonScope + { + void setEnterScope(bool value); + void setParseLine(bool value); + void initNextstatement(); + void linkNextStatement(ComparisonScope nextScope); + } +} + diff --git a/LineParser/Tags/Logic/Value.cs b/LineParser/Tags/Logic/Value.cs new file mode 100644 index 0000000..b1cfe4b --- /dev/null +++ b/LineParser/Tags/Logic/Value.cs @@ -0,0 +1,9 @@ +using System; + +namespace Compiler +{ + public interface Value + { + } +} + diff --git a/LineParser/Tags/Operators/AndOrOperator.cs b/LineParser/Tags/Operators/AndOrOperator.cs new file mode 100644 index 0000000..87c7458 --- /dev/null +++ b/LineParser/Tags/Operators/AndOrOperator.cs @@ -0,0 +1,9 @@ +using System; + +namespace Compiler +{ + public interface AndOrOperator + { + } +} + diff --git a/LineParser/Tags/Operators/ComparisonOperator.cs b/LineParser/Tags/Operators/ComparisonOperator.cs new file mode 100644 index 0000000..cd9ea80 --- /dev/null +++ b/LineParser/Tags/Operators/ComparisonOperator.cs @@ -0,0 +1,9 @@ +using System; + +namespace Compiler +{ + public interface ComparisonOperator + { + } +} + diff --git a/LineParser/Variables/Values/BooleanValue.cs b/LineParser/Variables/Values/BooleanValue.cs new file mode 100644 index 0000000..4ef79d5 --- /dev/null +++ b/LineParser/Variables/Values/BooleanValue.cs @@ -0,0 +1,17 @@ +using System; + +namespace Compiler +{ + public class BooleanValue : Logic, BoolType{ + + public bool value; + + public BooleanValue(bool inputValue){ + base.currentType = WordTypes.booleanValue; + base.word = "Bool Value"; + value = inputValue; + } + + } +} + diff --git a/LineParser/Variables/Values/CalculationValue.cs b/LineParser/Variables/Values/CalculationValue.cs new file mode 100644 index 0000000..737b48a --- /dev/null +++ b/LineParser/Variables/Values/CalculationValue.cs @@ -0,0 +1,16 @@ +using System; + +namespace Compiler +{ + public class CalculationValue : Logic + { + int lineNumber; + + public CalculationValue(int lineNumber){ + this.lineNumber = lineNumber; + base.currentType = WordTypes.calculationValue; + } + + } +} + diff --git a/LineParser/Variables/Values/NumberValue.cs b/LineParser/Variables/Values/NumberValue.cs new file mode 100644 index 0000000..3717da0 --- /dev/null +++ b/LineParser/Variables/Values/NumberValue.cs @@ -0,0 +1,22 @@ +using System; + +namespace Compiler +{ + public class NumberValue : Logic{ + + public double value = 0; + + public NumberValue(string word){ + base.currentType = WordTypes.number; + base.word = word; + double.TryParse (word, out value); + } + + public NumberValue(double value){ + base.currentType = WordTypes.number; + base.word = value.ToString(); + this.value = value; + } + } +} + diff --git a/LineParser/Variables/Values/TextValue.cs b/LineParser/Variables/Values/TextValue.cs new file mode 100644 index 0000000..829350a --- /dev/null +++ b/LineParser/Variables/Values/TextValue.cs @@ -0,0 +1,28 @@ +using System; + +namespace Compiler +{ + public class TextValue : Logic{ + + public string value; + + public TextValue(string word){ + base.currentType = WordTypes.textString; + base.word = word; + + if (word [0] == '"' && word [word.Length - 1] == '"') + removeQoutes (); + else + value = word; + } + + private void removeQoutes(){ + if (word.Length < 3) + value = ""; + else + value = word.Substring (1, word.Length - 2); + } + + } +} + diff --git a/LineParser/Variables/Values/UnknownLogic.cs b/LineParser/Variables/Values/UnknownLogic.cs new file mode 100644 index 0000000..c1a2b9b --- /dev/null +++ b/LineParser/Variables/Values/UnknownLogic.cs @@ -0,0 +1,17 @@ +using System; + +namespace Compiler +{ + public class UnknownLogic : Logic { + + int lineNumber; + + public UnknownLogic(int lineNumber){ + this.lineNumber = lineNumber; + base.currentType = WordTypes.unknown; + } + + } + +} + diff --git a/LineParser/Variables/Variable.cs b/LineParser/Variables/Variable.cs new file mode 100644 index 0000000..58e81fb --- /dev/null +++ b/LineParser/Variables/Variable.cs @@ -0,0 +1,85 @@ +using System; + +namespace Compiler +{ + + public class Variable : Logic, BoolType + { + public VariableTypes variableType; + public string name; + public bool isCalcVar = false; + public bool isReturnCalcVar = false; + + private double numberValue; + private bool boolValue; + private string stringValue; + + public bool isForLoopVariable = false; + + public Variable(){ + variableType = VariableTypes.unknown; + } + + public Variable(string name){ + this.name = name; + this.word = name; + variableType = VariableTypes.None; + } + public Variable(string name, string newValue, bool isCalcVar = false){ + this.name = name; + this.word = name; + variableType = VariableTypes.textString; + stringValue = newValue; + this.isCalcVar = isCalcVar; + } + public Variable(string name, double newValue, bool isCalcVar = false){ + this.name = name; + this.word = name; + variableType = VariableTypes.number; + numberValue = newValue; + this.isCalcVar = isCalcVar; + } + public Variable(string name, bool newValue, bool isCalcVar = false){ + this.name = name; + this.word = name; + variableType = VariableTypes.boolean; + boolValue = newValue; + this.isCalcVar = isCalcVar; + } + + + + + + public void setValue(double newValue){ + variableType = VariableTypes.number; + numberValue = newValue; + } + public void setValue(string newValue){ + variableType = VariableTypes.textString; + stringValue = newValue; + } + public void setValue(bool newValue){ + variableType = VariableTypes.boolean; + boolValue = newValue; + } + + public void setValue(){ + variableType = VariableTypes.None; + } + + + public double getNumber(){ + return numberValue; + } + + public bool getBool(){ + return boolValue; + } + + public string getString(){ + return stringValue; + } + } +} + diff --git a/LineParser/Variables/VariableTypes.cs b/LineParser/Variables/VariableTypes.cs new file mode 100644 index 0000000..1ae9af2 --- /dev/null +++ b/LineParser/Variables/VariableTypes.cs @@ -0,0 +1,13 @@ + +namespace Compiler +{ + public enum VariableTypes{ + number, + boolean, + textString, + None, + unsigned, + unknown + }; +} + diff --git a/LineParser/Variables/Variables.cs b/LineParser/Variables/Variables.cs new file mode 100644 index 0000000..6412a2a --- /dev/null +++ b/LineParser/Variables/Variables.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using B83.ExpressionParser; +using Runtime; +using ErrorHandler; + +namespace Compiler +{ + + public class Variables + { + public List variableList = new List(); + + //Later fix! + //Should be possible to avoid all the else if statements. + public void addVariable(Variable newVar, ExpressionParser scopePareser, int lineNumber){ + //First we check if the variable we are trying to add already exists, if it does we change the value of it. + //Otherwise create a new variable + int tempCont = containsVariable (newVar.name); + if (tempCont >= 0) { + variableList [tempCont] = newVar; + + if (newVar.variableType == VariableTypes.boolean) + changeExistingVariable (tempCont, newVar.getBool (), scopePareser); + else if (newVar.variableType == VariableTypes.number) + changeExistingVariable (tempCont, newVar.getNumber (), scopePareser); + else if (newVar.variableType == VariableTypes.textString) + changeExistingVariable (tempCont, newVar.getString (), scopePareser); + else if(newVar.variableType == VariableTypes.None) + changeExistingVariable (tempCont, newVar.getString (), scopePareser); + else + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.addOrChangeUnsupportedVariableType.ToString(), null); + + } + else { + if (newVar.variableType != VariableTypes.unknown && newVar.variableType != VariableTypes.unsigned) { + variableList.Add (newVar); + if (newVar.variableType == VariableTypes.number) + scopePareser.AddConst (newVar.name, () => newVar.getNumber ()); + } + else + ErrorHandler.ErrorMessage.sendErrorMessage (lineNumber, ErrorType.System, SystemFailureErrorType.addOrChangeUnsupportedVariableType.ToString(), null); + + } + + } + + + #region Alteration methods + public void changeExistingVariable(int index, double newValue, ExpressionParser scopeParser){ + removeFromParser (variableList [index].name, scopeParser); + + variableList [index].setValue (newValue); + scopeParser.AddConst(variableList [index].name, () => variableList [index].getNumber()); + } + + public void changeExistingVariable(int index, string newValue, ExpressionParser scopeParser){ + removeFromParser (variableList [index].name, scopeParser); + variableList [index].setValue (newValue); + } + + public void changeExistingVariable(int index, bool newValue, ExpressionParser scopeParser){ + removeFromParser (variableList [index].name, scopeParser); + variableList [index].setValue (newValue); + } + + public void changeExistingVariable(int index, ExpressionParser scopeParser){ + removeFromParser (variableList [index].name, scopeParser); + variableList [index].setValue (); + } + + void removeFromParser(string name, ExpressionParser scopeParser){ + if (scopeParser.containgsConst (name)) + scopeParser.RemoveConst (name); + } + #endregion + + + #region searchFunctions + public int containsVariable(string name){ + for (int i = 0; i < variableList.Count; i++) + if (variableList [i].name == name) + return i; + + + return -1; + } + + public int containsVariableOfType(string name, VariableTypes checkType){ + for (int i = 0; i < variableList.Count; i++) + if (variableList [i].name == name) + if (variableList [i].variableType == checkType) + return i; + else + return -1; + + return -1; + } + #endregion + + + public void printVariableList(){ + foreach (Variable v in variableList) + Print.print (v.name + " Num: " + v.getNumber () + " Bool: " + v.getBool () + " String: " + v.getString ()); + + } + } + + + +} + diff --git a/LineParser/bin/Debug/LineParser.dll b/LineParser/bin/Debug/LineParser.dll new file mode 100644 index 0000000..3db1727 Binary files /dev/null and b/LineParser/bin/Debug/LineParser.dll differ diff --git a/LineParser/bin/Debug/LineParser.dll.meta b/LineParser/bin/Debug/LineParser.dll.meta new file mode 100644 index 0000000..cc6a9e4 --- /dev/null +++ b/LineParser/bin/Debug/LineParser.dll.meta @@ -0,0 +1,25 @@ +fileFormatVersion: 2 +guid: 54a5ac61b77308749a1a4bf2f6c49f6d +timeCreated: 1496606432 +licenseType: Free +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Any: + enabled: 1 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/LineParser/bin/Debug/LineParser.pdb b/LineParser/bin/Debug/LineParser.pdb new file mode 100644 index 0000000..049cbfc Binary files /dev/null and b/LineParser/bin/Debug/LineParser.pdb differ diff --git a/LineParser/bin/Debug/LineParser.pdb.meta b/LineParser/bin/Debug/LineParser.pdb.meta new file mode 100644 index 0000000..430b367 --- /dev/null +++ b/LineParser/bin/Debug/LineParser.pdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 397e9d89cd72d704297ce233e28261b5 +timeCreated: 1496606432 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/LineParser/bin/Debug/sync.ffs_db b/LineParser/bin/Debug/sync.ffs_db new file mode 100644 index 0000000..d79aaba Binary files /dev/null and b/LineParser/bin/Debug/sync.ffs_db differ diff --git a/LineParser/countRows.py b/LineParser/countRows.py new file mode 100644 index 0000000..3283f08 --- /dev/null +++ b/LineParser/countRows.py @@ -0,0 +1,11 @@ +import glob + +fileList = glob.glob('./**/*.cs', recursive = True) +print(len(fileList), " files.") + +rows = 0 +for file in fileList: + with open(file, 'r') as f: + rows += sum(1 for line in f) + +print(rows) diff --git a/LineParser/obj/Debug/Compiler.csproj.CoreCompileInputs.cache b/LineParser/obj/Debug/Compiler.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..3f9d4b1 --- /dev/null +++ b/LineParser/obj/Debug/Compiler.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +df9ac10051b48dc0a890de5aee53326683f228b5 diff --git a/LineParser/obj/Debug/Compiler.csproj.FileListAbsolute.txt b/LineParser/obj/Debug/Compiler.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..65c1945 --- /dev/null +++ b/LineParser/obj/Debug/Compiler.csproj.FileListAbsolute.txt @@ -0,0 +1,35 @@ +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\bin\Debug\LineParser.dll +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\bin\Debug\LineParser.pdb +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\obj\Debug\Compiler.csprojResolveAssemblyReference.cache +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\obj\Debug\LineParser.dll +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\obj\Debug\LineParser.pdb +C:\Users\FreddeFrallan\Desktop\LOL\LineParser\LineParser\obj\Debug\Compiler.csprojResolveAssemblyReference.cache +C:\Users\FreddeFrallan\Desktop\LOL\LineParser\LineParser\obj\Debug\LineParser.dll +C:\Users\FreddeFrallan\Desktop\LOL\LineParser\LineParser\obj\Debug\LineParser.pdb +C:\Users\FreddeFrallan\Desktop\LOL\LineParser\LineParser\bin\Debug\LineParser.dll +C:\Users\FreddeFrallan\Desktop\LOL\LineParser\LineParser\bin\Debug\LineParser.pdb +C:\Users\FreddeFrallan\Documents\GitHub\Hello-Python-Compiler\LineParser\bin\Debug\LineParser.dll +C:\Users\FreddeFrallan\Documents\GitHub\Hello-Python-Compiler\LineParser\bin\Debug\LineParser.pdb +C:\Users\FreddeFrallan\Documents\GitHub\Hello-Python-Compiler\LineParser\obj\Debug\LineParser.dll +C:\Users\FreddeFrallan\Documents\GitHub\Hello-Python-Compiler\LineParser\obj\Debug\LineParser.pdb +C:\Users\Jonathan\Documents\GitHub\TestCompiler\LineParser\bin\Debug\LineParser.dll +C:\Users\Jonathan\Documents\GitHub\TestCompiler\LineParser\bin\Debug\LineParser.pdb +C:\Users\Jonathan\Documents\GitHub\TestCompiler\LineParser\obj\Debug\LineParser.dll +C:\Users\Jonathan\Documents\GitHub\TestCompiler\LineParser\obj\Debug\LineParser.pdb +C:\Users\Tifos\Documents\GitHub\TestCompiler\LineParser\bin\Debug\LineParser.dll +C:\Users\Tifos\Documents\GitHub\TestCompiler\LineParser\bin\Debug\LineParser.pdb +C:\Users\Tifos\Documents\GitHub\TestCompiler\LineParser\obj\Debug\LineParser.dll +C:\Users\Tifos\Documents\GitHub\TestCompiler\LineParser\obj\Debug\LineParser.pdb +C:\Users\Jonathan\Documents\GitHub\TestCompiler\LineParser\obj\Debug\Compiler.csprojResolveAssemblyReference.cache +C:\Users\Jonathan\Documents\GitHub\compiler\LineParser\obj\Debug\Compiler.csprojResolveAssemblyReference.cache +C:\Users\Jonathan\Documents\GitHub\compiler\LineParser\obj\Debug\LineParser.dll +C:\Users\Jonathan\Documents\GitHub\compiler\LineParser\bin\Debug\LineParser.dll +C:\Users\Jonathan\Documents\GitHub\compiler\LineParser\bin\Debug\LineParser.pdb +C:\Users\Jonathan\Documents\GitHub\compiler\LineParser\obj\Debug\LineParser.pdb +C:\Users\Tifos\Documents\GitHub\compiler\LineParser\bin\Debug\LineParser.dll +C:\Users\Tifos\Documents\GitHub\compiler\LineParser\bin\Debug\LineParser.pdb +C:\Users\Tifos\Documents\GitHub\compiler\LineParser\obj\Debug\LineParser.dll +C:\Users\Tifos\Documents\GitHub\compiler\LineParser\obj\Debug\LineParser.pdb +C:\Users\Tifos\Documents\GitHub\compiler\LineParser\obj\Debug\Compiler.csproj.CoreCompileInputs.cache +C:\Users\Tifos\Documents\GitHub\compiler\LineParser\obj\Debug\Compiler.csprojResolveAssemblyReference.cache +C:\Users\Jonathan\Documents\GitHub\compiler\LineParser\obj\Debug\Compiler.csproj.CoreCompileInputs.cache diff --git a/LineParser/obj/Debug/Compiler.csprojResolveAssemblyReference.cache b/LineParser/obj/Debug/Compiler.csprojResolveAssemblyReference.cache new file mode 100644 index 0000000..72c7c2c Binary files /dev/null and b/LineParser/obj/Debug/Compiler.csprojResolveAssemblyReference.cache differ diff --git a/LineParser/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/LineParser/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..ebb752c Binary files /dev/null and b/LineParser/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/LineParser/obj/Debug/LineParser.csproj.FileListAbsolute.txt b/LineParser/obj/Debug/LineParser.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..75b250c --- /dev/null +++ b/LineParser/obj/Debug/LineParser.csproj.FileListAbsolute.txt @@ -0,0 +1,4 @@ +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\bin\Debug\LineParser.dll +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\bin\Debug\LineParser.pdb +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\obj\Debug\LineParser.dll +C:\Users\FreddeFrallan\Documents\GitHub\If Game\plugins\LineParser\LineParser\obj\Debug\LineParser.pdb diff --git a/LineParser/obj/Debug/LineParser.dll b/LineParser/obj/Debug/LineParser.dll new file mode 100644 index 0000000..3db1727 Binary files /dev/null and b/LineParser/obj/Debug/LineParser.dll differ diff --git a/LineParser/obj/Debug/LineParser.pdb b/LineParser/obj/Debug/LineParser.pdb new file mode 100644 index 0000000..049cbfc Binary files /dev/null and b/LineParser/obj/Debug/LineParser.pdb differ diff --git a/LineParser/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/LineParser/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 0000000..e69de29 diff --git a/LineParser/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/LineParser/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 0000000..e69de29 diff --git a/LineParser/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/LineParser/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 0000000..e69de29 diff --git a/LineParser/obj/Release/Compiler.csproj.CoreCompileInputs.cache b/LineParser/obj/Release/Compiler.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..4178d18 --- /dev/null +++ b/LineParser/obj/Release/Compiler.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +a8ca14afb972976d36384874364e04774b37b311