示例#1
0
        /// <summary>
        /// Gets the data type of the very first variable in the expression. Might want to replace with a more sophisticated type checking system later.
        /// Right now it finds the type of first variable and assume the rest of the expression lines up properly.
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="vars"></param>
        /// <returns></returns>
        public static PezLexType GetTypeOfFirstVar(Node exp, List <Lexeme> vars) //exp is right subtree of assignment operation ast.
        {
            PezLexType   type = PezLexType.unid;
            Queue <Node> nq   = new Queue <Node>();

            nq.Enqueue(exp);
            while (nq.Count > 0)
            {
                Node n = nq.Dequeue();

                for (int i = 0; i < vars.Count; i++)
                {
                    if (vars[i].token == n.data.token)
                    {
                        return(vars[i].LType);
                    }
                }

                if (n.left != null)
                {
                    nq.Enqueue(n.left);
                }

                if (n.right != null)
                {
                    nq.Enqueue(n.right);
                }
            }
            return(type);
        }
示例#2
0
文件: TranslateC.cs 项目: Tsohg/pez
        /// <summary>
        /// Writes assignment statements in which the variable is both declared and assigned a value.
        /// </summary>
        /// <param name="ast"></param>
        /// <param name="scope"></param>
        private void WriteAssignmentState(Node ast, int scope)
        {
            AppendScope(scope);
            Node   exp;
            string partial = " " + ast.left.data.token + " " + ast.data.token + " ";
            //variables.Add(ast.left.data); //ast.left will always be the name of the variable being assigned.
            PezLexType type = Parser.FindLexDataType(ast);

TopOfSwitch:
            switch (type)
            {
            case PezLexType.id:     //variable only assignment operation
                //access the first variable being operated on and return its type
                type = Parser.GetTypeOfFirstVar(ast.right, variables);
                goto TopOfSwitch;     //repeat with found datatype.

            case PezLexType._int:
                source.Append("int" + partial);        //for now, we are only doing integers so this is the type.
                exp = ast.right;                       //This subset tree of the assignment ast is the expression/value.
                source.Append(Parser.GetInfixExpression(exp));
                ast.left.data.LType = PezLexType._int; //change identifer to int.
                variables.Add(ast.left.data);          //add to variables table.
                break;

            case PezLexType._float:
                source.Append("float" + partial); //for now, we are only doing integers so this is the type.
                exp = ast.right;                  //This subset tree of the assignment ast is the expression/value.
                source.Append(Parser.GetInfixExpression(exp));
                ast.left.data.LType = PezLexType._float;
                variables.Add(ast.left.data);
                break;

            case PezLexType._double:
                source.Append("double" + partial); //for now, we are only doing integers so this is the type.
                exp = ast.right;                   //This subset tree of the assignment ast is the expression/value.
                source.Append(Parser.GetInfixExpression(exp));
                ast.left.data.LType = PezLexType._double;
                variables.Add(ast.left.data);
                break;

            case PezLexType._string:     //add strings BEFORE going to C if necessary.
                source.Append("char*" + partial);
                source.Append(ProcessAssignmentStringState(ast.right));
                ast.left.data.LType = PezLexType._string;
                variables.Add(ast.left.data);
                break;

            default: throw new Exception("TranslateC:WriteAssignmentState:: PezLexType is not a C primitive data type or used variable is not declared on Statement Number: " + statementNum);
            }
            source.AppendLine(";");
            //string test = Parser.GetInfixExpression(ast.right);
        }
示例#3
0
        public static PezLexType FindLexDataType(Node root)
        {
            PezLexType   type = PezLexType.unid;
            Queue <Node> nq   = new Queue <Node>();

            nq.Enqueue(root);
            int idTally = 0;

            while (nq.Count > 0)
            {
                Node n = nq.Dequeue();

                if (n.data.LType == PezLexType.id)
                {
                    idTally++;
                }

                if (IsType(n.data.LType))
                {
                    return(n.data.LType);
                }

                if (n.left != null)
                {
                    nq.Enqueue(n.left);
                }

                if (n.right != null)
                {
                    nq.Enqueue(n.right);
                }
            }
            if (idTally > 1) //identifier in the case that only variables are used in operations rather than types. should be > 1 because assignment ops always have at least 1 identifier.
            {
                return(PezLexType.id);
            }
            Console.Out.WriteLine(type.ToString());
            return(type);
        }
示例#4
0
        public static bool IsType(PezLexType type)
        {
            string[] en = Enum.GetNames(typeof(PezLexType));
            int      t  = (int)type;
            int      r  = -1; //max range

            for (int i = 0; i < en.Length; i++)
            {
                if (en[i] == Enum.GetName(typeof(PezLexType), PezLexType._double))
                {
                    r = i;
                    break;
                }
            }
            if (t < r)
            {
                return(true);       //_int should ALWAYS be @ 0 in PezLexType.
            }
            else
            {
                return(false);
            }
        }
示例#5
0
文件: Lexeme.cs 项目: Tsohg/pez
 public Lexeme(PezLexType type, string token)
 {
     LType      = type;
     this.token = token;
 }
示例#6
0
文件: Lexer.cs 项目: Tsohg/pez
        /// <summary>
        /// Returns the next lexeme/token in the file based on a list of separators defined in PezSym.
        /// </summary>
        /// <returns>The next lexeme/token in a file.</returns>
        private Lexeme Next()
        {
            Lexeme lex;

            StringBuilder sb = new StringBuilder();

            if (!HasNextChar())
            {
                return(new Lexeme(PezLexType.termin, eof));
            }

            //Note: file[offset] is the current character we are looking at.

            //whitespace is first because i expect to read in a stream of \t when if statements pop up to determine scope.
            if (char.IsWhiteSpace(file[offset])) //we count \t as a scope token. \r\n is our terminating token.
            {
                switch (file[offset])
                {
                case '\t':
                    lex = new Lexeme(PezLexType.scoper, ";t");     // ; will be my marker for escape characters. ;t = \t but easier to recognize in output. ;rn = \r\n
                    offset++;
                    return(lex);

                case '\r':     //\r\n
                    lex = new Lexeme(PezLexType.termin, ";rn");
                    if (HasNextChar(1) && file[offset + 1] == '\n')
                    {
                        offset++;     //skip \n
                    }
                    return(lex);

                default:
                    offset++;
                    return(Next());    //if bugs happen, it's probably here
                }
            }
            else if (file[offset] == '"') //string literal beginning. anything surrounded in quotations is a string.
            {
                sb.Append(file[offset]);  //add quotation
                offset++;
                while (HasNextChar() && file[offset] != '"')
                {
                    sb.Append(file[offset]);
                    offset++;
                }
                sb.Append(file[offset]); //should be a closing quotation.
                offset++;
                //check to see if someone missed a quotation
                if (!HasNextChar() && sb[sb.Length - 1] != '"')
                {
                    throw new Exception("Lexer:StringLiteral:: Missing Quotation.");
                }
                lex = new Lexeme(PezLexType._string, sb.ToString());
                return(lex);
            }
            else if (char.IsLetter(file[offset])) //read until space as an identifier or type name. note: ids can be types.
            {
                while (HasNextChar() && char.IsLetterOrDigit(file[offset]))
                {
                    sb.Append(file[offset]);
                    offset++;
                }
                lex = new Lexeme(PezLexType.id, sb.ToString());
                return(lex);
            }
            else if (char.IsDigit(file[offset])) //read value until space. test to see if it is an integer or float.
            {
                PezLexType type = PezLexType.unid;
                while (HasNextChar() && (char.IsDigit(file[offset]) || file[offset] == '.'))
                {
                    if (file[offset] == '.')
                    {
                        type = PezLexType._float;
                    }
                    sb.Append(file[offset]);
                    offset++;
                }
                if (type == PezLexType.unid) //probably an integer so lets test.
                {
                    int val;
                    if (!int.TryParse(sb.ToString(), out val))
                    {
                        throw new Exception("Lexer:Digit:: Value is too big for an integer.");
                    }

                    lex = new Lexeme(PezLexType._int, sb.ToString());
                    return(lex);
                }
                else //type of float OR double. but we assume double here for now.
                {
                    float  val;
                    double dval;
                    if (!float.TryParse(sb.ToString(), out val)) //too big for a float
                    {
                        if (!double.TryParse(sb.ToString(), out dval))
                        {
                            throw new Exception("Lexer:Digit:: Value is too big to be contained within a double.");
                        }

                        //return it as a double
                        lex = new Lexeme(PezLexType._double, sb.ToString());
                        return(lex);
                    }
                    //it can fit in a float so return it as float
                    lex = new Lexeme(PezLexType._float, sb.ToString());
                    return(lex);
                }
            }
            else if ((39 < file[offset]) && (file[offset] < 48) || file[offset] == '=') //42 - 47 are basic ops 40 and 41 are ( )
            {
                if (file[offset] == 40)
                {
                    lex = new Lexeme(PezLexType.l_paren, file[offset].ToString()); // (
                    offset++;
                    return(lex);
                }
                else if (file[offset] == 41)
                {
                    lex = new Lexeme(PezLexType.r_paren, file[offset].ToString()); // )
                    offset++;
                    return(lex);
                }
                //theoretically can use .= .+ .- as operators...
                while (HasNextChar() && (41 < file[offset]) && (file[offset] < 48) || file[offset] == '=') //(41 < c < 48) //TODO: Move assignment to boolean lex for expressions later.
                {
                    sb.Append(file[offset]);
                    offset++;
                }
                lex = new Lexeme(PezLexType.op, sb.ToString());
                return(lex);
            }
            else if (HasNextChar() && file[offset] == ':') //range operator or colon operators.
            {
                sb.Append(file[offset]);
                offset++;
                if (HasNextChar() && file[offset] == ':') //specifically range operators at the moment.
                {
                    sb.Append(file[offset]);
                    offset++;
                    lex = new Lexeme(PezLexType.op, sb.ToString());
                    return(lex);
                }
                else
                {
                    throw new Exception("Invalid range operator at: " + offset);
                }
            }
            else if (file[offset] == '#')//# will be my comment symbol much like R language.
            {
                //ignore the rest of the line by finding \r\n then going offset++ then return next()
                while (true)
                {
                    offset++;
                    if (!HasNextChar())
                    {
                        return(new Lexeme(PezLexType.termin, eof));
                    }
                    if (file[offset] == '\r')
                    {
                        offset++;
                        if (HasNextChar() && file[offset] == '\n')
                        {
                            offset++;
                            return(new Lexeme(PezLexType.termin, ";rn"));
                        }
                        else
                        {
                            throw new Exception("Lexer:Next:: ;r not followed by ;n. Pez requires Windows CRLF line endings to function.");
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Lexer:Next:: Unidentified token encountered at offset: " + offset);
            }
        }