Example #1
0
 /// <summary>
 /// Create a binary expression
 /// </summary>
 public SyntaxExpr(Token function, SyntaxExpr param1, SyntaxExpr param2)
 {
     mParameters = new List <SyntaxExpr>();
     mFunction   = function;
     mParameters.Add(param1);
     mParameters.Add(param2);
 }
Example #2
0
        /// <summary>
        /// Make a bit declaration.  First parameter is declaration (with optional
        /// array parameter).  Second parameter is optional assignment.
        /// </summary>
        public SyntaxExpr ParseBitStatement(string[] rejects)
        {
            // Create "bit" statement
            SyntaxExpr expr = new SyntaxExpr(Accept("bit"));

            if (mToken.Type != eTokenType.Identifier)
            {
                Reject("Expecting a variable name", rejects);
                return(expr);
            }
            // Create declaration (array size is optional parameter)
            Token      variableName = Accept();
            SyntaxExpr declaration  = new SyntaxExpr(variableName);

            if (mTokenName == "[")
            {
                declaration.AddParam(ParseParen());
            }

            // First parameter is declaration
            expr.AddParam(declaration);

            // Second parameter (optional) is assignment statement
            if (mTokenName == "=")
            {
                expr.AddParam(new SyntaxExpr(Accept(), new SyntaxExpr(variableName), ParseExpr()));
            }

            return(expr);
        }
Example #3
0
        /// <summary>
        /// Parse multiple statements until 'box', 'end', 'else', or 'elif'
        /// is found.  Returns the statements that are parsed.
        /// Adds declarations to the box locals.  Never returns NULL.
        /// </summary>
        public SyntaxExpr ParseStatements(SyntaxBox box, bool topLevel)
        {
            // Create an "{" expression, which (for now means "statements")
            SyntaxExpr statements = new SyntaxExpr(mInternalTokenStatement);

            // While not end of file and not end of box and not new box
            while (mTokenName != "" &&
                   mTokenName != "box" &&
                   mTokenName != "end" &&
                   mTokenName != "else" &&
                   mTokenName != "elif")
            {
                // Skip blank statements
                while (mTokenName == ";")
                {
                    Accept();
                }

                // Parse the statement
                SyntaxExpr statement = ParseStatement(box, topLevel);
                if (statement != null)
                {
                    statements.AddParam(statement);
                }

                while (mTokenName == ";")
                {
                    Accept();
                }
            }
            return(statements);
        }
Example #4
0
        /// <summary>
        /// Parse a constant declaration (only "int" type is supported)
        /// </summary>
        SyntaxExpr ParseConstStatement()
        {
            // Create "const" statement
            SyntaxExpr expr = new SyntaxExpr(Accept("const"));

            if (mTokenName != "int")
            {
                Reject("Expecting keyword 'int'", REJECT_LINE);
                return(expr);
            }
            // First parameter is the type, "int"
            expr.AddParam(new SyntaxExpr(Accept()));

            // Variable name must be identifier
            if (mToken.Type != eTokenType.Identifier)
            {
                Reject("Expecting a variable name", REJECT_LINE);
                return(expr);
            }
            Token variableName = Accept();

            // Const statement requires an assignment
            if (mTokenName != "=")
            {
                Reject("Expecting '=' - Assignment is required");
                return(expr);
            }
            // Second parameter is the assignment expression
            expr.AddParam(new SyntaxExpr(Accept(), new SyntaxExpr(variableName), ParseExpr()));

            return(expr);
        }
Example #5
0
 /// <summary>
 /// Append a parameter to the parameters list.
 /// </summary>
 public void AddParam(SyntaxExpr e)
 {
     if (mParameters == null)
     {
         mParameters = new List <SyntaxExpr>();
     }
     mParameters.Add(e);
 }
Example #6
0
        /// <summary>
        /// Parse an array or function call
        /// </summary>
        SyntaxExpr ParseExprArrayOrFunction()
        {
            SyntaxExpr result = ParseExprAtom();

            if (mTokenName == "(" || mTokenName == "[")
            {
                result = ParseParameters(result);
            }
            return(result);
        }
Example #7
0
        /// <summary>
        /// Parse an expression
        /// </summary>
        public SyntaxExpr ParseExpr()
        {
            SyntaxExpr result = ParseExprTernary();

            // Optionally build a range function
            if (mTokenName == ":" || mTokenName == "..")
            {
                return(new SyntaxExpr(Accept(), result, ParseExprTernary()));
            }
            return(result);
        }
Example #8
0
        /// <summary>
        /// Parse equality
        /// </summary>
        SyntaxExpr ParseExprCompare()
        {
            SyntaxExpr result = ParseExprPlus();

            // Optionally build equality function
            if (mTokenName == "==" || mTokenName == "!=")
            {
                return(new SyntaxExpr(Accept(), result, ParseExprPlus()));
            }
            return(result);
        }
Example #9
0
        /// <summary>
        /// Parse (*, /, %)
        /// </summary>
        SyntaxExpr ParseExprMult()
        {
            SyntaxExpr result = ParseUnary();

            // Build multiplication function
            while (mTokenName == "*" || mTokenName == "/" || mTokenName == "%")
            {
                result = new SyntaxExpr(Accept(), result, ParseUnary());
            }
            return(result);
        }
Example #10
0
        /// <summary>
        /// Parse (+, -)
        /// </summary>
        SyntaxExpr ParseExprPlus()
        {
            SyntaxExpr result = ParseExprXor();

            // Build addition function
            while (mTokenName == "+" || mTokenName == "-")
            {
                result = new SyntaxExpr(Accept(), result, ParseExprXor());
            }

            return(result);
        }
Example #11
0
        /// <summary>
        /// Parse an if statement (expects 'if' at the input)
        /// </summary>
        SyntaxExpr ParseIfStatement(SyntaxBox box)
        {
            // Parse "if" token, condition, and statements
            Token ifToken = mToken;

            Accept("if");
            SyntaxExpr ifExpr = new SyntaxExpr(ifToken);

            ifExpr.AddParam(ParseIfCond());
            ifExpr.AddParam(ParseStatements(box, false));

            // Parse "elif" statements
            SyntaxExpr elseExpr = ifExpr;

            while (mTokenName == "elif")
            {
                // Parse "elif" token, condition, and statements
                // NOTE: "elif" token is converted to "if"
                Connect(ifToken, mToken);
                Accept("elif");
                SyntaxExpr newIf = new SyntaxExpr(ifToken);
                newIf.AddParam(ParseIfCond());
                newIf.AddParam(ParseStatements(box, false));

                // Convert the new "elif" to "else if"
                elseExpr.AddParam(newIf);
                elseExpr = newIf;
            }

            // Parse the "else" clause (if it exists)
            if (mTokenName == "else")
            {
                Connect(ifToken, mToken);
                Accept("else");
                elseExpr.AddParam(ParseStatements(box, false));
            }

            // Parse end of box statement
            if (mTokenName == "end")
            {
                mToken.InfoString = "end if";
                Connect(ifToken, mToken);
                Accept();
            }
            else
            {
                Reject("Expecting 'end' - end of if statement body", REJECT_BOX);
            }

            // Parse "else" part
            return(ifExpr);
        }
Example #12
0
        /// <summary>
        /// Parse parameters '(' param1 ',' param2 ... ')'
        /// NOTE: firstParam is the function name, and will be the first
        /// parameter of the result.  The open and close '()' or '[]' will
        /// be connected.
        /// </summary>
        SyntaxExpr ParseParameters(SyntaxExpr firstParam)
        {
            // Read open '(' or '['
            Token openToken = mToken;

            if (openToken != "(" && openToken != "[")
            {
                throw new Exception("Compiler error: Expecting '(' or '[' while parsing parameters");
            }

            // Create an expression with '(' or '['
            SyntaxExpr result        = new SyntaxExpr(Accept(), firstParam);
            string     tokenExpected = openToken == "(" ? ")" : "]";

            string [] rejectTokens = openToken == "(" ? REJECT_PAREN : REJECT_BRACKET;

            // Empty () function call?
            if (mTokenName == tokenExpected)
            {
                // Return an empty () or []
                Connect(openToken, mToken);
                Accept();
                return(result);
            }

            // Parse all parameters
            result.AddParam(ParseExpr());
            while (mTokenName == ",")
            {
                Accept();
                result.AddParam(ParseExpr());
            }

            // If not ended properly, reject this expression
            if (mTokenName != tokenExpected)
            {
                // The rest of the line is rejected
                Reject("Expecting '" + tokenExpected + "' or ','", rejectTokens);
            }

            if (mTokenName == tokenExpected)
            {
                Connect(openToken, mToken);
                Accept();
            }
            return(result);
        }
Example #13
0
        /// <summary>
        /// Parse ternary expression (a ? (b : c))
        /// </summary>
        SyntaxExpr ParseExprTernary()
        {
            SyntaxExpr result = ParseExprCompare();

            // Or a ternary operator
            if (mTokenName == "?")
            {
                Token      q  = Accept();
                SyntaxExpr t1 = ParseExprTernary();
                if (mTokenName != ":")
                {
                    q.Reject("Matching ':' was not found");
                    return(Reject("Expecting a ':' to separate expression for the ternary '?' operator", REJECT_LINE));
                }
                result = new SyntaxExpr(q, result, new SyntaxExpr(Accept(), t1, ParseExprTernary()));
            }
            return(result);
        }
Example #14
0
        /// <summary>
        /// Parse an 'if' or 'elif' condition
        /// </summary>
        SyntaxExpr ParseIfCond()
        {
            // Parse condition
            if (mTokenName != "(")
            {
                return(Reject("Expecting '('", REJECT_LINE));
            }
            Token      open   = Accept();
            SyntaxExpr result = ParseExpr();

            if (mTokenName != ")")
            {
                return(Reject("Expecting ')' - end of of expression", REJECT_LINE));
            }
            Connect(open, mToken);
            Accept(")");
            return(result);
        }
Example #15
0
        /// <summary>
        /// Read the open '(' or '[' parse the expression and connect
        /// the ']' or ')'.  Returns the expression that was parsed.
        /// </summary>
        SyntaxExpr ParseParen()
        {
            // Shouldn't ever happen
            if (mTokenName != "(" && mTokenName != "[")
            {
                throw new Exception("Compiler error: Expecting '[' or '(' while parsing paren");
            }

            // Read open '(' or '[' and create an Expr
            Token  openToken     = mToken;
            string tokenExpected = openToken == "(" ? ")" : "]";

            string [] rejectTokens = openToken == "(" ? REJECT_PAREN : REJECT_BRACKET;
            Accept();


            // Empty () or []?
            if (mTokenName == tokenExpected)
            {
                // Return an empty () or []
                Connect(openToken, mToken);
                Reject("Expecting a parameter");
                SyntaxExpr emptyExpr = new SyntaxExpr(Accept()); // Error, use ')' or ']'
                return(emptyExpr);
            }

            // Parse all parameters (then add separator)
            SyntaxExpr result = ParseExpr();

            // If not ended properly, append a reject line
            if (mTokenName != tokenExpected)
            {
                // The rest of the line is rejected
                Reject("Expecting '" + tokenExpected + "'", rejectTokens);
            }
            if (mTokenName == tokenExpected)
            {
                Connect(openToken, mToken);
                Accept();
            }
            return(result);
        }
Example #16
0
        /// <summary>
        /// Generate an expression list (as if this were lisp)
        /// </summary>
        void ToString(SyntaxExpr expr, StringBuilder sb, int level)
        {
            if (level >= 7)
            {
                sb.Append("*OVF*");
                return;
            }

            if (Count == 0)
            {
                sb.Append(expr.mFunction);
                return;
            }

            if (level != 0)
            {
                sb.Append("(");
            }

            if (expr.mFunction == "(")
            {
                sb.Append("'");
            }
            sb.Append(expr.mFunction);
            if (expr.mFunction == "(")
            {
                sb.Append("'");
            }

            foreach (SyntaxExpr param in expr.mParameters)
            {
                sb.Append(", ");
                ToString(param, sb, level + 1);
            }

            if (level != 0)
            {
                sb.Append(")");
            }
        }
Example #17
0
        /// <summary>
        /// Rejects tokens until one of the stopTokens is found.
        /// Marks at least one token with the error message.
        /// </summary>
        SyntaxExpr Reject(string errorMessage, string [] stopTokens)
        {
            // Mark all tokens to end of line with an error
            Reject(errorMessage);
            SyntaxExpr result = new SyntaxExpr(mToken);

            // Skip the rest of this statement
            while (true)
            {
                if (mTokenName == "")
                {
                    return(result);
                }
                foreach (string token in stopTokens)
                {
                    if (mTokenName == token)
                    {
                        return(result);
                    }
                }
                Accept();
            }
        }
Example #18
0
        /// <summary>
        /// Evaluate a constant.  If there is an error, the symbol
        /// that caused it is rejected and the error bit is set.
        /// </summary>
        public static EvaluateConst Eval(SymbolTable symbols, SyntaxExpr expr)
        {
            if (expr == null)
            {
                return(new EvaluateConst());
            }

            if (expr.Count != 0)
            {
                expr.Function.Reject("Not yet supported");
                return(new EvaluateConst());
            }

            if (expr.Function.Name.Length == 0)
            {
                return(new EvaluateConst());
            }

            // Parse number
            if (char.IsDigit(expr.Function.Name[0]))
            {
                EvaluateConst result = new EvaluateConst();
                result.Resolved = true;

                // Attempt to scan hexadecimal value
                if (expr.Function.Name.Length >= 3 &&
                    char.ToUpper(expr.Function.Name[1]) == 'X' &&
                    long.TryParse(expr.Function.Name.Substring(2),
                                  NumberStyles.AllowHexSpecifier,
                                  CultureInfo.CurrentCulture, out result.ValueInt))
                {
                    result.WasHex = true;
                    return(result);
                }

                // Attempt to scan decimal value
                if (long.TryParse(expr.Function.Name, out result.ValueInt))
                {
                    return(result);
                }

                expr.Function.Reject("Error reading value");
                return(new EvaluateConst());
            }

            // Parse identifier
            if (expr.Function.Type == eTokenType.Identifier)
            {
                Symbol symbol = symbols.FindSymbol(expr.Function);
                if (symbol == null)
                {
                    expr.Function.Reject("Undefined symbol");
                    return(new EvaluateConst());
                }
                if (symbol.Decl.TypeName.Name != "int")
                {
                    expr.Function.Reject("Constant value must be of type 'int'");
                    return(new EvaluateConst());
                }
                if (symbol.ResolvedName == "")
                {
                    expr.Function.Reject("Unresolved symbol");
                    return(new EvaluateConst());
                }
                // We got the type, mark the symbol
                expr.Function.AppendMessage(symbol.ResolvedName);
                return(new EvaluateConst(symbol.ConstValue));
            }

            expr.Function.Reject("Unrecognized symbol in constant expression");
            return(new EvaluateConst());
        }
Example #19
0
        /// <summary>
        /// Parse a single statement, which could be an expression.
        /// Adds declaratins to the box locals.
        /// NOTE: This can return NULL if there are no statements.
        /// </summary>
        public SyntaxExpr ParseStatement(SyntaxBox box, bool topLevel)
        {
            while (mTokenName == "else" || mTokenName == "elif")
            {
                Reject("This '" + mTokenName + "' is not inside an 'if' statement");
                Accept();
            }

            // Check statement keywords first
            bool       needsSemicolon = true;
            SyntaxExpr result         = null;

            if (mTokenName == "bit")
            {
                // Parse bit statement (optionally followed by assignment)
                if (!topLevel)
                {
                    Reject("'bit' declarations are only allowed at the top level");
                }
                result = ParseBitStatement(REJECT_LINE);
            }
            else if (mTokenName == "const")
            {
                // Parse const declaration
                if (!topLevel)
                {
                    Reject("'const' declarations are only allowed at the top level");
                }
                result = ParseConstStatement();
            }
            else if (mTokenName == "if")
            {
                // Parse if statement
                needsSemicolon = false;
                result         = ParseIfStatement(box);
            }
            else
            {
                // Parse an expression
                result = ParseExpr();

                // Assignment statement?
                if (mTokenName == "=")
                {
                    // Generate an assignment statement
                    result = new SyntaxExpr(Accept(), result, ParseExpr());
                }
            }

            // Ensure we have a valid statement
            if (needsSemicolon && mTokenName != ";")
            {
                Reject("Expecting end of statement separator ';'", REJECT_LINE);
            }
            if (mTokenName == ";")
            {
                Accept();
            }

            return(result);
        }