예제 #1
0
 /// <summary>
 /// Test if the given token represents opening bracket of a byte array, i.e. "]".
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsOpeningByteArrayBracket(Token token)
 {
     SpecialCharacterToken sctoken = token as SpecialCharacterToken;
     if (sctoken == null)
         return false;
     return (sctoken.Value == '[');
 }
예제 #2
0
 /// <summary>
 /// Test for block argument prefix, defined in "3.4.4 Blocks".
 /// This is the colon in block argument.
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsBlockArgumentPrefix(Token token)
 {
     SpecialCharacterToken sctoken = token as SpecialCharacterToken;
     if (sctoken == null)
         return false;
     return (sctoken.Value == SemanticConstants.BlockArgumentPrefix);
 }
예제 #3
0
 /// <summary>
 /// Test if the token is opening delimiter for Primitive API call statement.
 /// This is IronSmalltalk extension to the grammer.
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsApiOpeningDelimiter(Token token)
 {
     BinarySelectorToken apitoken = token as BinarySelectorToken;
     if (apitoken == null)
         return false;
     return (apitoken.Value == SemanticConstants.PrimitiveOpeningDelimiter);
 }
예제 #4
0
        protected override LiteralNode ParseLiteral(ILiteralNodeParent parent, Token token)
        {
            if ((parent is ArrayLiteralNode) && Parser.IsOpeningParenthesis(token))
            {
                // Stupid VSE allows declarations of arrays like: #( 1 2 ( 3 4 ) 5 6),
                // which is identical to: #( 1 2 #( 3 4 ) 5 6).
                // Only the inner (child) arrays may omit the hash prefix.
                // Here we emulate this and create a 'fake' hash token.
                // The fake hash token gets the same source positions and the parenthesis token.
                SpecialCharacterToken hash = new SpecialCharacterToken(SemanticConstants.LiteralArrayPrefix);
                hash.SetTokenValues(token.StartPosition, token.StopPosition, null);
                this.ResidueToken = token;
                return this.ParseArrayLiteral(parent, hash);
            }

            if (!Parser.IsLiteralArrayPrefix(token))
                return base.ParseLiteral(parent, token);

            Token token2 = this.GetNextTokenxx(Preference.Default);
            if (VseCompatibleParser.IsOpeningByteArrayBracket(token2))
                return this.ParseByteArrayLiteral(parent, (SpecialCharacterToken) token, (SpecialCharacterToken)token2);

            this.ResidueToken = token2;
            return base.ParseLiteral(parent, token);
        }
예제 #5
0
        private string GetTokenValue(Token token)
        {
            Type t = token.GetType();
            PropertyInfo[] infos = t.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
            Dictionary<string, string> map = new Dictionary<string, string>();
            foreach (PropertyInfo info in infos)
            {
                if (!(new string[] { "StartPosition", "StopPosition", "IsValid", "ScanError", "SourceString" }).Contains(info.Name))
                {
                    object value = info.GetValue(token, null);
                    map[info.Name] = String.Format("{0}", value);
                }
            }

            if ((map.Count == 1) && map.ContainsKey("Value"))
                return map["Value"];

            StringBuilder sb = new StringBuilder();
            foreach (var pair in map)
            {
                if (sb.Length != 0)
                    sb.Append(", ");
                sb.AppendFormat("{0}: {1}", pair.Key, pair.Value);
            }
            return sb.ToString();
        }
예제 #6
0
        protected virtual ParseTemporariesResult ParseTemporaries(FunctionNode function, Token token)
        {
            // PARSE: <temporaries> ::= '|' <temporary variable list> '|'
            ParseTemporariesResult result = new ParseTemporariesResult();
            if (!(token is VerticalBarToken))
            {
                this.ResidueToken = token;
                return result;
            }

            result.LeftBar = (VerticalBarToken)token;
            while (true)
            {
                token = this.GetNextTokenxx(Preference.VerticalBar);
                if (token is VerticalBarToken)
                {
                    // Done with temp variables.
                    result.RightBar = (VerticalBarToken)token;
                    return result;
                }
                if (token is IdentifierToken)
                {
                    result.Temporaries.Add(new TemporaryVariableNode(function, (IdentifierToken)token));
                }
                else
                {
                    this.ReportParserError(function, SemanticErrors.MissingClosingTempBar, token);
                    this.ResidueToken = token;
                    return result;
                }
            }
        }
예제 #7
0
        protected virtual BasicExpressionNode ParseBasicExpression(SemanticNode parent, Token token)
        {
            // PARSE: <basic expression> ::= <primary> [<messages> <cascaded messages>]
            BasicExpressionNode result = new BasicExpressionNode(parent);

            IPrimaryNode primary = this.ParsePrimary(result, token);
            if (primary == null)
            {
                this.ReportParserError(result, SemanticErrors.MissingPrimary, token);
                return result;
            }

            token = this.GetNextTokenxx(Preference.Default);
            this.ParseBaseicExpressionMessages(result, primary, token);
            return result;
        }
예제 #8
0
 /// <summary>
 /// Test if the given token represents opening parenthesis, i.e. "(".
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsOpeningParenthesis(Token token)
 {
     SpecialCharacterToken sctoken = token as SpecialCharacterToken;
     if (sctoken == null)
         return false;
     return (sctoken.Value == SemanticConstants.OpeningParenthesis);
 }
예제 #9
0
 /// <summary>
 /// Test if the token is reference to the reserved identifier "self".
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsIdentifierTrue(Token token)
 {
     IdentifierToken idtoken = token as IdentifierToken;
     if (idtoken == null)
         return false;
     return (idtoken.Value == SemanticConstants.True);
 }
예제 #10
0
        protected virtual MessageSequenceNode ParseMessages(IMessageSequenceParentNode parent, Token token, MessageType type)
        {
            // <messages> ::=
            //      (<unary message>+ <binary message>* [<keyword message>] ) |
            //      (<binary message>+ [<keyword message>] ) |
            //      <keyword message>
            // <unary message> ::= unarySelector
            // <binary message> ::= binarySelector <binary argument>
            // <binary argument> ::= <primary> <unary message>*
            // <keyword message> ::= (keyword <keyword argument> )+
            // <keyword argument> ::= <primary> <unary message>* <binary message>*

            if ((token is IdentifierToken) && ((type & MessageType.Unary) != 0))
                // (<unary message>+ <binary message>* [<keyword message>] )
                return this.ParseUnaryBinaryKeywordMessageSequence(parent, (IdentifierToken)token);

            if ((token is BinarySelectorToken) && ((type & MessageType.Binary) != 0))
                // (<binary message>+ [<keyword message>] )
                return this.ParseBinaryKeywordMessageSequence(parent, (BinarySelectorToken)token);

            if ((token is KeywordToken) && ((type & MessageType.Keyword) != 0))
                // <keyword message>
                return this.ParseKeywordMessageSequence(parent, (KeywordToken)token);

            this.ResidueToken = token; // Not for us ... let others give it a try.
            return null;
        }
예제 #11
0
 /// <summary>
 /// Parses a message sequence as defined in X3J20 "3.4.5.3 Messages".
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="token">First token of the message node. If the token is message token, it is returned in the residueToken parameter.</param>
 /// <returns>Message sequence node or null if the given token is not a message token.</returns>
 /// <remarks>
 /// This mehtod does not registers errors if the given token is not a message token.
 /// The 'offending' token is returned in the residueToken parameter, and it is 
 /// responsibility of the called to determine what to do.
 /// </remarks>
 protected virtual MessageSequenceNode ParseMessages(IMessageSequenceParentNode parent, Token token)
 {
     return this.ParseMessages(parent, token, MessageType.All);
 }
예제 #12
0
        /// <summary>
        /// Parse a literal node as described in X3J20 "3.4.6 Literals".
        /// </summary>
        /// <remarks>
        /// If the given token is not a legal token for a literal node,
        /// it is simply returned in the residueToken output parameter, 
        /// and the function returns null.
        /// </remarks>
        /// <param name="parent">Parent node that defines the literal node.</param>
        /// <param name="token">First token of the literal node.</param>
        /// <returns>A literal node, or null in case of non-literal token.</returns>
        protected virtual LiteralNode ParseLiteral(ILiteralNodeParent parent, Token token)
        {
            // PARSE: <literal> ::= <number literal> | <string literal> | <character literal> |
            //      <symbol literal> | <selector literal> | <array literal>

            // <string literal> ::= quotedString
            if (token is StringToken)   // 'example'
                return new StringLiteralNode(parent, (StringToken)token);
            // <symbol literal> ::= hashedString
            if (token is HashedStringToken) // #'example'
                return new SymbolLiteralNode(parent, (HashedStringToken)token);
            // <character literal> ::= quotedCharacter
            if (token is CharacterToken)    // $e
                return new CharacterLiteralNode(parent, (CharacterToken)token);
            // <selector literal> ::= quotedSelector
            if (token is QuotedSelectorToken)   // #example ..or.. #example: ..or.. #example:example: ..or.. #+
                return new SelectorLiteralNode(parent, (QuotedSelectorToken)token);

            // <number literal> ::= ['-'] <number>
            if (token is NegativeSignToken)
                return this.ParseNegativeNumericLiteralNode(parent, (NegativeSignToken)token);
            // <number> ::= integer | float | scaledDecimal
            if (token is SmallIntegerToken)
                return new SmallIntegerLiteralNode(parent, (SmallIntegerToken)token, null);
            if (token is LargeIntegerToken)
                return new LargeIntegerLiteralNode(parent, (LargeIntegerToken)token, null);
            if (token is FloatEToken)
                return new FloatELiteralNode(parent, (FloatEToken)token, null);
            if (token is FloatDToken)
                return new FloatDLiteralNode(parent, (FloatDToken)token, null);
            if (token is ScaledDecimalToken)
                return new ScaledDecimalLiteralNode(parent, (ScaledDecimalToken)token, null);

            // <array literal> ::= '#(' <array element>* ')'
            // <array element> ::= <literal> | identifier
            if (Parser.IsLiteralArrayPrefix(token))
                return this.ParseArrayLiteral(parent, (SpecialCharacterToken)token);

            this.ResidueToken = token;
            return null;
        }
예제 #13
0
        protected virtual KeywordArgumentNode ParseKeywordArgument(KeywordMessageNode parent, Token token)
        {
            // PARSE: <keyword argument> ::= <primary> <unary message>* <binary message>*
            KeywordArgumentNode result = new KeywordArgumentNode(parent);

            IPrimaryNode primary = this.ParsePrimary(result, token);
            if (primary == null)
            {
                this.ReportParserError(result, SemanticErrors.MissingPrimary, token);
                return result;
            }

            token = this.GetNextTokenxx(Preference.Default);

            BinaryOrBinaryUnaryMessageSequenceNode messages = null;
            if (token is IdentifierToken)
                // <unary message>*
                messages = this.ParseUnaryBinaryMessageSequence(result, (IdentifierToken)token);
            else if (token is BinarySelectorToken)
                messages = this.ParseBinaryMessageSequence(result, (BinarySelectorToken)token);
            else
                this.ResidueToken = token;

            result.SetContents(primary, messages);
            return result;
        }
예제 #14
0
        // <expression> ::=
        //      <assignment> |
        //      <basic expression>
        // <assignment> ::= <assignment target> assignmentOperator <expression>
        // <basic expression> ::= <primary> [<messages> <cascaded messages>]
        // <assignment target> := identifier
        // <primary> ::=
        //      identifier |
        //      <literal> |
        //      <block constructor> |
        //      ( '(' <expression> ')' )
        protected virtual ExpressionNode ParseExpression(SemanticNode parent, Token token)
        {
            // Tricky ... first try for <assignment>
            if (token is IdentifierToken)
            {
                // In here, we either have an <assignment target> or <primary> of a <basic expression>
                IdentifierToken identifier = (IdentifierToken)token;

                // Try to check for assignmentOperator
                token = this.GetNextTokenxx(Preference.Default);
                if (token is AssignmentOperatorToken)
                    // OK, it's <assignment>
                    return this.ParseAssignment(parent, identifier, (AssignmentOperatorToken)token);

                // Must recover ... it is a <basic expression> anyway.
                // PARSE: identifier [<messages> <cascaded messages>]
                BasicExpressionNode result = new BasicExpressionNode(parent);
                this.ParseBaseicExpressionMessages(result, new VariableReferenceleNode(result, identifier), token);
                return result;
            };
            return this.ParseBasicExpression(parent, token);
        }
예제 #15
0
        protected virtual CascadeMessageSequenceNode ParseCascadeMessageSequenceNode(ICascadeMessageSequenceParentNode parent, Token semicolon)
        {
            // PARSE: <cascaded messages> ::= (';' <messages>)*
            if (!Parser.IsCascadeDelimiter(semicolon))
            {
                this.ResidueToken = semicolon;
                return null; // Not a cascade message ... return null.
            }
            CascadeMessageSequenceNode result = new CascadeMessageSequenceNode(parent, (SpecialCharacterToken)semicolon);

            Token token = this.GetNextTokenxx(Preference.Default);
            MessageSequenceNode messages = this.ParseMessages(result, token);

            if (messages == null)
            {
                this.ReportParserError(result, SemanticErrors.MissingMessagePattern, token);
                return result;
            }

            token = this.GetNextTokenxx(Preference.Default);

            CascadeMessageSequenceNode nextCascade = null;
            if (Parser.IsCascadeDelimiter(token))
                nextCascade = this.ParseCascadeMessageSequenceNode(result, (SpecialCharacterToken)token);
            else
                this.ResidueToken = token;

            result.SetContents(messages, nextCascade);
            return result;
        }
예제 #16
0
        protected virtual Token GetNextTokenxx(Preference preference)
        {
            Token token;

            if (this.ResidueToken != null)
            {
                token = this.ResidueToken;
                this.ResidueToken = null;
                return token;
            }

            do
            {
                token = this.Scanner.GetToken(preference);

                //if ((parent.Comments != null) && (token is CommentToken))
                //    parent.Comments.Add((CommentToken)token);

            } while (token is WhitespaceToken);
            return token;
        }
예제 #17
0
 protected virtual MethodArgumentNode ParseMethodArgument(MethodNode parent, Token token)
 {
     // PARSE: identifier      ... NB: X3J20 bug - definition missing ... but this one is easy.
     if (!(token is IdentifierToken))
     {
         this.ReportParserError(parent, SemanticErrors.MissingMethodArgument, token);
         this.ResidueToken = token;
         // NB: MethodArgumentNode must be able to handle null for arg. name token.
         return new MethodArgumentNode(parent, null);
     }
     return new MethodArgumentNode(parent, (IdentifierToken)token);
 }
예제 #18
0
 /// <summary>
 /// Test if the given token represents a literal array prefix hash mark, i.e. "#".
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsLiteralArrayPrefix(Token token)
 {
     SpecialCharacterToken sctoken = token as SpecialCharacterToken;
     if (sctoken == null)
         return false;
     return (sctoken.Value == SemanticConstants.LiteralArrayPrefix);
 }
예제 #19
0
 protected virtual IPrimaryNode ParsePrimary(IPrimaryParentNode parent, Token token)
 {
     // PARSE: <primary> ::= identifier | <literal> | <block constructor> | ( '(' <expression> ')' )
     if (token is IdentifierToken)
         return new VariableReferenceleNode(parent, (IdentifierToken)token);
     else if (Parser.IsBlockStartDelimiter(token))
         return this.ParseBlock(parent, (SpecialCharacterToken)token);
     else if (Parser.IsOpeningParenthesis(token))
         return this.ParseParenthesizedExpression(parent, (SpecialCharacterToken)token);
     else
         return this.ParseLiteral(parent, token);
 }
예제 #20
0
        protected virtual StatementNode ParseStatement(IStatementParentNode parent, Token token)
        {
            // PARSE: <statements> ::=
            //      (<return statement> ['.'] ) |
            //      (<expression> ['.' [<statements>]])

            if ((token is EofToken) || Parser.IsBlockEndDelimiter(token))
            {
                this.ResidueToken = token;
                return null;
            }

            if (token is ReturnOperatorToken)
                return this.ParseReturnStatement(parent, (ReturnOperatorToken)token);
            else
                return this.ParseStatementSequence(parent, token);
        }
예제 #21
0
        protected virtual StatementSequenceNode ParseStatementSequence(IStatementParentNode parent, Token token)
        {
            // PARSE: (<expression> ['.' [<statements>]])
            StatementSequenceNode result = new StatementSequenceNode(parent);

            ExpressionNode expression = this.ParseExpression(result, token);
            if (expression == null)
                this.ReportParserError(result, SemanticErrors.MissingExpression, token);

            SpecialCharacterToken period = null;
            token = this.GetNextTokenxx(Preference.Default);
            if (Parser.IsStatementDelimiter(token))
            {
                period = (SpecialCharacterToken)token;
            }
            else
            {
                result.SetContents(expression, null, null);
                this.ResidueToken = token;
                return result;
            }

            // ['.' [<statements>]])
            token = this.GetNextTokenxx(Preference.NegativeSign);
            if (token is EofToken)
            {
                result.SetContents(expression, period, null);
                this.ResidueToken = token;
                return result;
            }
            if (Parser.IsBlockEndDelimiter(token))
            {
                result.SetContents(expression, period, null);
                this.ResidueToken = token;
                return result;
            }
            else if (Parser.IsStatementDelimiter(token))
            {
                this.ReportParserError(result, SemanticErrors.MissingStatement, token);
                result.SetContents(expression, period, null);
                this.ResidueToken = token;
                return result;
            }

            StatementNode nextStatement = this.ParseStatement(result, token);
            result.SetContents(expression, period, nextStatement);
            return result;
        }
예제 #22
0
 /// <summary>
 /// Test for block end bracket, defined in "3.4.4 Blocks".
 /// This is the closing square bracket "]" used for defining blocks.
 /// </summary>
 /// <param name="token">Token to perform the test on.</param>
 /// <returns>True, if the test succeeds, otherwise false.</returns>
 public static bool IsBlockEndDelimiter(Token token)
 {
     SpecialCharacterToken sctoken = token as SpecialCharacterToken;
     if (sctoken == null)
         return false;
     return (sctoken.Value == SemanticConstants.BlockEndDelimiter);
 }
예제 #23
0
        protected virtual void ParseBaseicExpressionMessages(BasicExpressionNode expression, IPrimaryNode primary, Token token)
        {
            MessageSequenceNode messages = this.ParseMessages(expression, token);
            if (messages == null)
            {
                expression.SetContents(primary, null, null);
                return;
            }

            token = this.GetNextTokenxx(Preference.Default);
            CascadeMessageSequenceNode cascadeMessages = this.ParseCascadeMessageSequenceNode(expression, token);

            expression.SetContents(primary, messages, cascadeMessages);
        }