コード例 #1
0
ファイル: LexerTest.cs プロジェクト: todor-dk/IronSmalltalk
        public void Test_3_5_4_Keywords_B()
        {
            // An unadorned identifier is an identifier which is not immediately preceded by a '#'.
            // If a ':' followed by an '=' immediately follows an unadorned identifier,
            // with no intervening white space, then the token is to be parsed as an
            // identifier followed by an assignmentOperator not as an keyword followed by an '='.
            Scanner lexer = this.GetLexer("isGood1Time:=");
            // Identifier token
            object obj = lexer.GetToken();

            Assert.IsInstanceOfType(obj, typeof(IdentifierToken));
            Assert.IsNotInstanceOfType(obj, typeof(KeywordToken));
            IdentifierToken token = (IdentifierToken)obj;

            Assert.IsTrue(token.IsValid);
            Assert.IsNull(token.ScanError);
            Assert.AreEqual(0, token.StartPosition.Position);
            Assert.AreEqual(10, token.StopPosition.Position);
            Assert.AreEqual("isGood1Time", token.Value);
            // Assignment token
            obj = lexer.GetToken();
            Assert.IsInstanceOfType(obj, typeof(AssignmentOperatorToken));
            AssignmentOperatorToken assign = (AssignmentOperatorToken)obj;

            Assert.IsTrue(assign.IsValid);
            Assert.IsNull(assign.ScanError);
            Assert.AreEqual(11, assign.StartPosition.Position);
            Assert.AreEqual(12, assign.StopPosition.Position);

            // Should be the last one
            obj = lexer.GetToken();
            Assert.IsInstanceOfType(obj, typeof(EofToken));
        }
コード例 #2
0
ファイル: LexerTest.cs プロジェクト: todor-dk/IronSmalltalk
        public void Test_3_5_5_Operators_E()
        {
            Scanner lexer = this.GetLexer(":=");
            object  obj   = lexer.GetToken();

            Assert.IsInstanceOfType(obj, typeof(AssignmentOperatorToken));
            AssignmentOperatorToken token = (AssignmentOperatorToken)obj;

            Assert.IsTrue(token.IsValid);
            Assert.IsNull(token.ScanError);
            Assert.AreEqual(0, token.StartPosition.Position);
            Assert.AreEqual(1, token.StopPosition.Position);
            // Should be the last one
            obj = lexer.GetToken();
            Assert.IsInstanceOfType(obj, typeof(EofToken));
        }
コード例 #3
0
        protected virtual AssignmentNode ParseAssignment(SemanticNode parent, IdentifierToken identifier, AssignmentOperatorToken assignmentOperator)
        {
            // PARSE: <assignment> ::= <assignment target> assignmentOperator <expression>
            //      <assignment target> := identifier
            AssignmentNode result = new AssignmentNode(parent, identifier, assignmentOperator);

            Token          token      = this.GetNextTokenxx(Preference.NegativeSign);
            ExpressionNode expression = this.ParseExpression(result, token);

            if (expression == null)
            {
                this.ReportParserError(result, SemanticErrors.MissingExpression, token);
            }
            else
            {
                result.SetContents(expression);
            }

            return(result);
        }
コード例 #4
0
        public IEnumerable <IToken> Tokenize(SafeStreamReader source)
        {
            uint lineNumber = 1;
            uint lexemeStartPositionInLine = 1;
            uint absolutePosition          = 1;
            var  maybeCurrentChar          = Option <int> .None;

            var currentLexemeBuffer = new StringBuilder();

            var maybeToken = Option <IToken> .None;;

            while ((maybeCurrentChar = source.Read()).IsSome)
            {
                var currentChar = maybeCurrentChar.Value();

                maybeToken = Option <IToken> .None;

                switch (currentChar)
                {
                case var c when string.IsNullOrWhiteSpace(char.ConvertFromUtf32(c)):
                    // if a whitespace was encountered - strip it
                    // and yield whatever in the buffer to the output

                    maybeToken = FlushBuffer(
                        currentLexemeBuffer,
                        ref absolutePosition,
                        lineNumber,
                        ref lexemeStartPositionInLine
                        );

                    if (maybeToken.IsSome)
                    {
                        yield return(maybeToken.ValueUnsafe());
                    }

                    switch (c)
                    {
                    case '\r':
                        yield return(source.Read()
                                     .Some <IToken>(cn =>
                                                    cn == '\n' ?
                                                    (IToken) new NewLineSymbolToken(
                                                        absolutePosition,
                                                        lineNumber,
                                                        lexemeStartPositionInLine
                                                        ) :
                                                    (IToken) new UnrecognizedToken(
                                                        $"\r{cn}",
                                                        absolutePosition,
                                                        lineNumber,
                                                        lexemeStartPositionInLine
                                                        )
                                                    )
                                     .None(new UnrecognizedToken(
                                               $"\r",
                                               absolutePosition,
                                               lineNumber,
                                               lexemeStartPositionInLine
                                               ))
                                     );

                        absolutePosition         += 2;
                        lineNumber               += 1;
                        lexemeStartPositionInLine = 1;

                        break;

                    case '\n':
                        yield return(new NewLineSymbolToken(
                                         absolutePosition,
                                         lineNumber,
                                         lexemeStartPositionInLine
                                         ));

                        absolutePosition         += 1;
                        lineNumber               += 1;
                        lexemeStartPositionInLine = 1;

                        break;

                    default:
                        absolutePosition          += 1;
                        lexemeStartPositionInLine += 1;
                        break;
                    }

                    break;

                case '.':
                    var currentLexeme = currentLexemeBuffer.ToString();

                    var maybeBeforeToken =
                        IntegerLiteralToken.FromString(
                            currentLexeme,
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            ) ||
                        IdentifierToken.FromString(
                            currentLexeme,
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            ) ||
                        UnrecognizedToken.FromString(
                            currentLexeme,
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            )
                    ;

                    var tokes =
                        source.Peek()
                        .Some <ImmutableList <IToken> >(c =>
                    {
                        var result        = ImmutableList <IToken> .Empty;
                        IToken tokenToAdd = null;

                        switch (c)
                        {
                        case var _ when IsDigit(char.ConvertFromUtf32(c)):
                            currentLexemeBuffer.Append('.');
                            return(ImmutableList <IToken> .Empty);

                        case '.':
                            absolutePosition += maybeBeforeToken
                                                .Map(t => (uint)t.Lexeme.Length)
                                                .IfNone(0);
                            lexemeStartPositionInLine += maybeBeforeToken
                                                         .Some(t => (uint)t.Lexeme.Length)
                                                         .None(0u);

                            tokenToAdd = new RangeSymbolToken(
                                absolutePosition,
                                lineNumber,
                                lexemeStartPositionInLine
                                );

                            result = maybeBeforeToken
                                     .ToImmutableList()
                                     .Add(tokenToAdd);
                            source.Read();
                            currentLexemeBuffer.Clear();
                            lexemeStartPositionInLine += (uint)(tokenToAdd?.Lexeme.Length ?? 0);
                            absolutePosition          += (uint)(tokenToAdd?.Lexeme.Length ?? 0);

                            return(result);

                        default:
                            absolutePosition += maybeBeforeToken
                                                .Map(t => (uint)t.Lexeme.Length)
                                                .IfNone(0);
                            lexemeStartPositionInLine += maybeBeforeToken
                                                         .Some(t => (uint)t.Lexeme.Length)
                                                         .None(0u);

                            tokenToAdd = new DotSymbolToken(
                                absolutePosition,
                                lineNumber,
                                lexemeStartPositionInLine
                                );

                            result = maybeBeforeToken
                                     .ToImmutableList()
                                     .Add(tokenToAdd);
                            currentLexemeBuffer.Clear();
                            lexemeStartPositionInLine += (uint)(tokenToAdd?.Lexeme.Length ?? 0);
                            absolutePosition          += (uint)(tokenToAdd?.Lexeme.Length ?? 0);

                            return(result);
                        }
                    })
                        .None(() =>
                    {
                        absolutePosition += maybeBeforeToken
                                            .Map(t => (uint)t.Lexeme.Length)
                                            .IfNone(0);
                        lexemeStartPositionInLine += maybeBeforeToken
                                                     .Some(t => (uint)t.Lexeme.Length)
                                                     .None(0u);

                        var tokenToAdd = new DotSymbolToken(
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            );

                        var result = maybeBeforeToken
                                     .ToImmutableList()
                                     .Add(tokenToAdd);
                        currentLexemeBuffer.Clear();
                        lexemeStartPositionInLine += (uint)(tokenToAdd?.Lexeme.Length ?? 0);
                        absolutePosition          += (uint)(tokenToAdd?.Lexeme.Length ?? 0);

                        return(result);
                    })
                    ;

                    foreach (var token in tokes)
                    {
                        yield return(token);
                    }

                    break;

                case '/':
                    maybeToken = FlushBuffer(
                        currentLexemeBuffer,
                        ref absolutePosition,
                        lineNumber,
                        ref lexemeStartPositionInLine
                        );
                    if (maybeToken.IsSome)
                    {
                        yield return(maybeToken.ValueUnsafe());
                    }

                    yield return(source.Peek()
                                 .Some <IToken>(c =>
                    {
                        switch (c)
                        {
                        case '/':
                            var commentContent = source.ReadLine();

                            var commentToken = new CommentToken(
                                $"/{commentContent}",
                                absolutePosition,
                                lineNumber,
                                lexemeStartPositionInLine
                                );

                            absolutePosition += (uint)commentContent.Length;
                            lineNumber += 1;
                            lexemeStartPositionInLine = 0;

                            return commentToken;

                        case '=':
                            var notEqualsToken = new NotEqualsOperatorToken(
                                absolutePosition,
                                lineNumber,
                                lexemeStartPositionInLine
                                );

                            source.Read();
                            absolutePosition += 1;
                            lexemeStartPositionInLine = 1;

                            return notEqualsToken;

                        default:
                            return new DivideOperatorToken(
                                (uint)source.BaseStream.Position,
                                lineNumber,
                                lexemeStartPositionInLine
                                );
                        }
                    })
                                 .None(() => new DivideOperatorToken(
                                           (uint)source.BaseStream.Position,
                                           lineNumber,
                                           lexemeStartPositionInLine
                                           )));

                    absolutePosition          += 1;
                    lexemeStartPositionInLine += 1;

                    break;

                case ':':
                    maybeToken = FlushBuffer(
                        currentLexemeBuffer,
                        ref absolutePosition,
                        lineNumber,
                        ref lexemeStartPositionInLine
                        );
                    if (maybeToken.IsSome)
                    {
                        yield return(maybeToken.ValueUnsafe());
                    }

                    yield return(source.Peek()
                                 .Filter(c => c == '=')
                                 .Some <IToken>(c =>
                    {
                        var result = new AssignmentOperatorToken(
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            );

                        source.Read();
                        absolutePosition += 1;
                        lexemeStartPositionInLine += 1;

                        return result;
                    })
                                 .None(new ColonSymbolToken(
                                           absolutePosition,
                                           lineNumber,
                                           lexemeStartPositionInLine
                                           )));

                    absolutePosition          += 1;
                    lexemeStartPositionInLine += 1;

                    break;

                case '>':
                    maybeToken = FlushBuffer(
                        currentLexemeBuffer,
                        ref absolutePosition,
                        lineNumber,
                        ref lexemeStartPositionInLine
                        );
                    if (maybeToken.IsSome)
                    {
                        yield return(maybeToken.ValueUnsafe());
                    }

                    yield return(source.Peek()
                                 .Filter(c => c == '=')
                                 .Some <IToken>(_ =>
                    {
                        var result = new GeOperatorToken(
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            );

                        source.Read();
                        absolutePosition += 1;
                        lexemeStartPositionInLine += 1;

                        return result;
                    })
                                 .None(new GtOperatorToken(
                                           (uint)absolutePosition,
                                           lineNumber,
                                           lexemeStartPositionInLine
                                           )));

                    absolutePosition          += 1;
                    lexemeStartPositionInLine += 1;

                    break;

                case '<':
                    maybeToken = FlushBuffer(
                        currentLexemeBuffer,
                        ref absolutePosition,
                        lineNumber,
                        ref lexemeStartPositionInLine
                        );
                    if (maybeToken.IsSome)
                    {
                        yield return(maybeToken.ValueUnsafe());
                    }

                    yield return(source.Peek()
                                 .Filter(c => c == '=')
                                 .Some <IToken>(_ =>
                    {
                        var result = new LeOperatorToken(
                            absolutePosition,
                            lineNumber,
                            lexemeStartPositionInLine
                            );

                        source.Read();
                        absolutePosition += 1;
                        lexemeStartPositionInLine += 1;

                        return result;
                    })
                                 .None(new LtOperatorToken(
                                           absolutePosition,
                                           lineNumber,
                                           lexemeStartPositionInLine
                                           )));

                    absolutePosition          += 1;
                    lexemeStartPositionInLine += 1;

                    break;

                case '*':
                case '%':
                case '+':
                case '-':
                case '=':
                case ',':
                case '[':
                case ']':
                case '(':
                case ')':
                case ';':
                    maybeToken = FlushBuffer(
                        currentLexemeBuffer,
                        ref absolutePosition,
                        lineNumber,
                        ref lexemeStartPositionInLine
                        );
                    if (maybeToken.IsSome)
                    {
                        yield return(maybeToken.ValueUnsafe());
                    }

                    yield return(SymbolLexemes
                                 .TryGetValue(((char)currentChar).ToString())
                                 .Some(cons => cons(
                                           absolutePosition,
                                           lineNumber,
                                           lexemeStartPositionInLine
                                           ))
                                 .None(() => new UnrecognizedToken(
                                           currentChar.ToString(),
                                           absolutePosition,
                                           lineNumber,
                                           lexemeStartPositionInLine
                                           )
                                       ));

                    absolutePosition          += 1;
                    lexemeStartPositionInLine += 1;

                    break;

                default:
                    currentLexemeBuffer.Append(char.ConvertFromUtf32(currentChar));
                    break;
                }
            }

            maybeToken = FlushBuffer(
                currentLexemeBuffer,
                ref absolutePosition,
                lineNumber,
                ref lexemeStartPositionInLine
                );
            if (maybeToken.IsSome)
            {
                yield return(maybeToken.ValueUnsafe());
            }
        }
コード例 #5
0
        /// <summary>
        /// Create and initialize a new assignment expression.
        /// </summary>
        /// <param name="parent">Parent node that defines this expression.</param>
        /// <param name="identifier">Identifier token of the assignment target.</param>
        /// <param name="token">Token representing the assignment operator.</param>
        protected internal AssignmentNode(SemanticNode parent, IdentifierToken identifier, AssignmentOperatorToken token)
            : base(parent)
        {
#if DEBUG
            if (identifier == null)
            {
                throw new ArgumentNullException("identifier");
            }
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }
#endif
            this.Target             = new AssignmentTargetNode(this, identifier);
            this.AssignmentOperator = token;
        }