コード例 #1
0
        public static ExpBase CreateExpression(CodeElement elem, Scope scope)
        {
            if (elem == null)
            {
                throw new Exception("Missing expression element");
            }

            // First non operator values
            switch (elem.Name)
            {
            case WordInt:
                return(new ExpInt(elem));

            case WordString:
                return(new ExpString(elem));

            case WordReal:
                return(new ExpFloat(elem));

            case WordBool:
                return(new ExpBool(elem));

            case WordExp:
                return(CreateExpression(elem.Codes().FirstOrDefault(), scope));

            case WordPar:
                return(CreateExpression(elem.Codes().FirstOrDefault(), scope));

            case "identifier":
                return(CreateExpVariable(elem, scope));

            case WordFuncCall:
                return(CreateExpFuncCall(elem, scope));
            }

            // Then binary operator values. All binary operators has two operants.
            CodeElement first = elem.Codes().FirstOrDefault();
            CodeElement next  = elem.Codes().FirstOrDefault(c => c != first);
            ExpBase     op1   = CreateExpression(first, scope);
            ExpBase     op2   = CreateExpression(next, scope);

            // For multiplication, division, subtraction, greaterThan and lowerThan the operants must be numbers.
            if (elem.Name == WordMul || elem.Name == WordDiv || elem.Name == WordSub || elem.Name == WordGt || elem.Name == WordLt)
            {
                // check type
                if (!ExpBase.IsNumber(op1))
                {
                    throw new Exception(string.Format("The left operant of '{0}', {1}, is not a number", elem.Name, elem.GetLineAndColumn()));
                }
                if (!ExpBase.IsNumber(op2))
                {
                    throw new Exception(string.Format("The right operant of '{0}', {1}, is not a number", elem.Name, elem.GetLineAndColumn()));
                }
            }

            // For 'equals' the operants must both be numbers or both be strings.
            if (elem.Name == WordEq)
            {
                if (!(ExpBase.IsNumber(op1, op2) || ExpBase.IsString(op1, op2)))
                {
                    throw new Exception(string.Format("Operants must both be numbers or both be strings: '{0}', {1}", elem.Name, elem.GetLineAndColumn()));
                }
            }

            switch (elem.Name)
            {
            case WordGt: return(new ExpGt(op1, op2));

            case WordLt: return(new ExpLt(op1, op2));

            case WordEq: return(new ExpEquals(op1, op2));

            case WordDiv: return(new ExpDivide(op1, op2));

            case WordMul:
                if (ExpBase.IsInt(op1, op2))
                {
                    return(new ExpMultiplyInt(op1, op2));
                }
                else
                {
                    return(new ExpMultiplyFloat(op1, op2));
                }

            case WordSub:
                if (ExpBase.IsInt(op1, op2))
                {
                    return(new ExpMinusInt(op1, op2));
                }
                else
                {
                    return(new ExpMinusFloat(op1, op2));
                }

            case WordSum:
                if (ExpBase.IsInt(op1, op2))
                {
                    return(new ExpSumInt(op1, op2));
                }
                else if (ExpBase.IsNumber(op1, op2))
                {
                    return(new ExpSumFloat(op1, op2));
                }
                else
                {
                    return(new ExpSumString(op1, op2));
                }

            default:
                throw new Exception(string.Format("Unknown expression element: '{0}'", elem.Name));
            }
        }
コード例 #2
0
ファイル: Variables.cs プロジェクト: Krixohub/IntoTheCode
        public void BuildVariable(DefType theType, string name, CodeElement elem)
        {
            if (Vars.ContainsKey(name))
            {
                throw new Exception(string.Format("A variable called '{0}', {1}, is allready declared", name, elem.GetLineAndColumn()));
            }

            ValueBase variable = ValueBase.Compile(theType, this, null);

            Vars.Add(name, variable);
        }
コード例 #3
0
ファイル: Scope.cs プロジェクト: Krixohub/IntoTheCode
 public DefType ExistsVariable(string name, CodeElement elem)
 {
     if (Vars.ExistsVariable(name))
     {
         return(Vars.GetVariable(name).ResultType);
     }
     else if (ParentScope != null)
     {
         return(ParentScope.ExistsVariable(name, elem));
     }
     else
     {
         throw new Exception(string.Format("A variable called '{0}', {1}, does not exists", name, elem.GetLineAndColumn()));
     }
 }
コード例 #4
0
        public static FuncCall CreateFuncCall(CodeElement elem, Scope scope)
        {
            // funcCall    = identifier '(' [exp {',' exp}] ')';

            CodeElement idElem = elem.Codes("identifier").First();
            string      name   = idElem.Value;

            Function theFunc = scope.GetFunction(name);

            var parameters = new List <ExpBase>();
            int i          = -1;

            foreach (CodeElement item in elem.Codes().Where(e => e != idElem))
            {
                var parm = CreateExpression(item, scope);
                if (++i == theFunc.Parameters.Count)
                {
                    throw new Exception(string.Format("Too many parameters for function '{0}', {1}", name, item.GetLineAndColumn()));
                }
                if (theFunc.Parameters[i].TheType == DefType.Int && !ExpBase.IsInt(parm))
                {
                    throw new Exception(string.Format("The parameter for function '{0}' must be an integer, {1}", name, item.GetLineAndColumn()));
                }
                if (theFunc.Parameters[i].TheType == DefType.Bool && !ExpBase.IsBool(parm))
                {
                    throw new Exception(string.Format("The parameter for function '{0}' must be a boolean, {1}", name, item.GetLineAndColumn()));
                }
                if (theFunc.Parameters[i].TheType == DefType.Bool && !ExpBase.IsNumber(parm))
                {
                    throw new Exception(string.Format("The parameter for function '{0}' must be a number, {1}", name, item.GetLineAndColumn()));
                }

                parameters.Add(parm);
            }
            if (i + 1 != theFunc.Parameters.Count)
            {
                throw new Exception(string.Format("Too few parameters for function '{0}', {1}", name, elem.GetLineAndColumn()));
            }

            var call = new FuncCall(theFunc, parameters);

            return(call);
        }
コード例 #5
0
        public static Declare CreateDeclare(CodeElement elem, bool isVariable)
        {
            CodeElement defType    = elem.Codes().FirstOrDefault();
            CodeElement identifier = elem.Codes("identifier").FirstOrDefault();

            Declare dec = new Declare()
            {
                TheName = identifier.Value
            };

            switch (defType.Name)
            {
            case WordTypeInt: dec.TheType = DefType.Int; break;

            case WordTypeStr: dec.TheType = DefType.String; break;

            case WordTypeReal: dec.TheType = DefType.Float; break;

            case WordTypeBool: dec.TheType = DefType.Bool; break;

            case WordTypeVoid:
                if (isVariable)
                {
                    throw new Exception(string.Format("Only functions can be 'void'. {0}", defType.GetLineAndColumn()));
                }
                dec.TheType = DefType.Void;
                break;

            default: throw new Exception(string.Format("The type '{0}' is not defined. {1}", defType.Value, defType.GetLineAndColumn()));
            }

            return(dec);
        }
コード例 #6
0
        public static void CreateFunctionDef(CodeElement elem, Scope scope)
        {
            // functionDef = typeAndId '(' [typeAndId {',' typeAndId}] ')' '{' scope '}';
            CodeElement defElem = elem.Codes(WordDeclare).First();
            var         def2    = CreateDeclare(defElem, false);
            Function    funcDef = new Function()
            {
                FuncType = def2.TheType, Name = def2.TheName
            };

            if (scope.Functions.ContainsKey(funcDef.Name))
            {
                throw new Exception(string.Format("A function called '{0}', {1}, is allready declared", funcDef.Name, elem.GetLineAndColumn()));
            }

            funcDef.Parameters = new List <Declare>();
            foreach (CodeElement item in elem.Codes(WordDeclare).Where(e => e != defElem))
            {
                var parm = CreateDeclare(item, true);
                funcDef.Parameters.Add(parm);
            }

            scope.Functions.Add(funcDef.Name, funcDef);
        }
コード例 #7
0
        public static Return CreateReturn(CodeElement elem, Scope scope, DefType resultType)
        {
            // return      = 'return' [exp] ';';

            var cmd = new Return();

            CodeElement expCode = elem.Codes().FirstOrDefault();

            if (expCode != null)
            {
                cmd.Expression = ExpressionBuilder.CreateExpression(expCode, scope);

                if (resultType == DefType.Bool && !ExpBase.IsBool(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a bool'. {0}", expCode.GetLineAndColumn()));
                }
                if (resultType == DefType.Int && !ExpBase.IsInt(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be an integer'. {0}", expCode.GetLineAndColumn()));
                }
                if (resultType == DefType.Float && !ExpBase.IsNumber(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a number'. {0}", expCode.GetLineAndColumn()));
                }
            }
            else
            if (resultType != DefType.Void)
            {
                throw new Exception(string.Format("This function must return a value. {0}", elem.GetLineAndColumn()));
            }

            return(cmd);
        }
コード例 #8
0
        public static While CreateWhile(CodeElement elem, Scope scope, DefType resultType)
        {
            // loop        = 'while' '(' exp ')' body;
            ExpBase expbase = ExpressionBuilder.CreateExpression(elem.Codes().First(), scope);
            var     cmd     = new While();

            cmd.Expression = expbase as ExpTyped <bool>;
            if (cmd.Expression == null)
            {
                throw new Exception(string.Format("The expression type must be a boolean, {0}", elem.GetLineAndColumn()));
            }

            cmd.Body = CreateBody(elem.Codes(WordBody).First(), scope, resultType, out bool ret);
            return(cmd);
        }
コード例 #9
0
        public static If CreateIf(CodeElement elem, Scope scope, DefType resultType, out bool alwaysReturnValue)
        {
            // if          = 'if' '(' exp ')' body ['else' body];
            ExpBase expbase = ExpressionBuilder.CreateExpression(elem.Codes().First(), scope);
            var     cmd     = new If();

            cmd.Expression = expbase as ExpTyped <bool>;
            if (cmd.Expression == null)
            {
                throw new Exception(string.Format("The expression type must be a boolean, {0}", elem.GetLineAndColumn()));
            }

            bool trueReturn;

            cmd.TrueStatement = CreateBody(elem.Codes(WordBody).First(), scope, resultType, out trueReturn);
            bool elseReturn;

            cmd.ElseStatement = CreateBody(elem.Codes(WordBody).Last(), scope, resultType, out elseReturn);
            alwaysReturnValue = trueReturn && elseReturn;
            return(cmd);
        }
コード例 #10
0
        public static Assign CreateAssign(CodeElement elem, Scope scope)
        {
            // assign      = identifier '=' exp ';';
            var         cmd    = new Assign();
            CodeElement idElem = elem.Codes(WordIdentifier).First();

            cmd.VariableName = idElem.Value;
            cmd.VariableType = scope.ExistsVariable(cmd.VariableName, idElem);

            CodeElement expCode = elem.Codes().Last();

            cmd.Expression = ExpressionBuilder.CreateExpression(expCode, scope);

            if (cmd.VariableType == DefType.Bool && !ExpBase.IsBool(cmd.Expression))
            {
                throw new Exception(string.Format("The expression must be a bool'. {0}", expCode.GetLineAndColumn()));
            }
            if (cmd.VariableType == DefType.Int && !ExpBase.IsInt(cmd.Expression))
            {
                throw new Exception(string.Format("The expression must be an integer'. {0}", expCode.GetLineAndColumn()));
            }
            if (cmd.VariableType == DefType.Float && !ExpBase.IsNumber(cmd.Expression))
            {
                throw new Exception(string.Format("The expression must be a number'. {0}", expCode.GetLineAndColumn()));
            }

            return(cmd);
        }
コード例 #11
0
        public static VariableDef CreateVariableDef(CodeElement elem, Scope scope)
        {
            // variableDef = typeAndId '=' exp ';';
            var def = CreateDeclare(elem.Codes(WordDeclare).First(), true);
            var cmd = new VariableDef()
            {
                Name = def.TheName, VariableType = def.TheType
            };

            if (elem.Codes().Count() == 2)
            {
                CodeElement expCode = elem.Codes().Last();
                cmd.Expression = ExpressionBuilder.CreateExpression(expCode, scope);

                if (cmd.VariableType == DefType.Bool && !ExpBase.IsBool(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a bool'. {0}", expCode.GetLineAndColumn()));
                }
                if (cmd.VariableType == DefType.Int && !ExpBase.IsInt(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be an integer'. {0}", expCode.GetLineAndColumn()));
                }
                if (cmd.VariableType == DefType.Float && !ExpBase.IsNumber(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a number'. {0}", expCode.GetLineAndColumn()));
                }
            }
            if (scope.ExistsFunction(cmd.Name))
            {
                throw new Exception(string.Format("A Function called '{0}', {1}, is declared", cmd.Name, elem.GetLineAndColumn()));
            }

            scope.Vars.BuildVariable(cmd.VariableType, cmd.Name, elem);
            return(cmd);
        }
コード例 #12
0
        public static OperationBase CreateVariableOrOperation(CodeElement elem, Scope scope, DefType resultType, out bool alwaysReturnValue)
        {
            alwaysReturnValue = false;
            OperationBase stm;

            switch (elem.Name)
            {
            case WordVariableDef:
                stm = CreateVariableDef(elem, scope);
                break;

            case WordAssign:
                stm = CreateAssign(elem, scope);
                break;

            case WordIf:
                stm = CreateIf(elem, scope, resultType, out alwaysReturnValue);
                break;

            case WordWhile:
            case WordLoop:
                stm = CreateWhile(elem, scope, resultType);
                break;

            case WordFuncCall:
                stm = CreateOperationFuncCall(elem, scope);
                break;

            case WordReturn:
                stm = CreateReturn(elem, scope, resultType);
                alwaysReturnValue = true;
                break;

            default:
                throw new Exception(string.Format("The operation type '{0}' is not allowed, {1}", elem.Name, elem.GetLineAndColumn()));
            }

            return(stm);
        }
コード例 #13
0
        public static void CreateFunctionInnerScope(CodeElement elem, Scope scope)
        {
            // functionDef = typeAndId '(' [typeAndId {',' typeAndId}] ')' '{' scope '}';
            CodeElement defElem = elem.Codes(WordDeclare).First();
            var         def2    = CreateDeclare(defElem, false);
            Function    funcDef;

            scope.Functions.TryGetValue(def2.TheName, out funcDef);

            Variables innerVariables = new Variables(null, null);

            foreach (CodeElement item in elem.Codes(WordDeclare).Where(e => e != defElem))
            {
                var parm = CreateDeclare(item, true);
                innerVariables.BuildVariable(parm.TheType, parm.TheName, item);
            }

            CodeElement scopeElem = elem.Codes(WordScope).First();

            bool alwaysReturns;

            funcDef.FunctionScope = CreateScope(scopeElem, innerVariables, scope, funcDef.FuncType, out alwaysReturns);

            if (funcDef.FuncType != DefType.Void && !alwaysReturns)
            {
                throw new Exception(string.Format("The function '{0}' must return a value, {1}", funcDef.Name, elem.GetLineAndColumn()));
            }
        }