예제 #1
0
        private void AddIdentifier(string value)
        {
            if (Identifiers.Any(e => e.Name.Equals(value)))
            {
                return;
            }

            int index = Identifiers.Count + 1;

            Identifiers.Add(new Identifier
            {
                Index = index,
                Type  = Lexemes.Any() ? Lexemes.Last()?.Token ?? "" : "",
                Name  = value
            }
                            );
        }
예제 #2
0
        public OuterLexemes Parse(string code)
        {
            int lineNumber    = 1;
            var lexemeBuilder = new StringBuilder();

            foreach (string symbol in code.Select(c => c.ToString()))
            {
                int realLineNumber = lineNumber;
                if (symbol.Equals("\n"))
                {
                    lineNumber++;
                }

                if (TrimDelimiters.Contains(symbol) || Delimiters.Contains(symbol))
                {
                    string lexeme = lexemeBuilder.ToString();

                    if (PredefinedWords.Contains(lexeme) || Operators.Contains(lexeme))
                    {
                        AddLexeme(lexeme, realLineNumber);
                    }
                    else if (IsIdentifier(lexeme))
                    {
                        // Duplicated identifier
                        if (Lexemes.Any() && Lexemes.Last().SubString.Equals("var") &&
                            Identifiers.Any(e => e.Name.Equals(lexeme)))
                        {
                            AddError($"Duplicate declaration of {lexeme} identifier", realLineNumber);
                            lexemeBuilder.Clear();
                            continue;
                        }

                        // Usage of undeclared identifier
                        if (Lexemes.Any() && !Lexemes.Last().SubString.Equals("var") &&
                            !Lexemes.Last().SubString.Equals("program") && !Identifiers.Any(e => e.Name.Equals(lexeme)))
                        {
                            AddError($"Usage of undeclared identifier: {lexeme}", realLineNumber);
                            lexemeBuilder.Clear();
                            continue;
                        }

                        AddIdentifier(lexeme);
                        AddLexeme(lexeme, realLineNumber, IdentifierType.Identifier);
                    }
                    else if (IsConstant(lexeme))
                    {
                        AddConstant(lexeme);
                        AddLexeme(lexeme, realLineNumber, IdentifierType.Constant);
                    }
                    else if (!string.IsNullOrEmpty(lexeme))
                    {
                        AddError($"Unknown lexeme: {lexeme}", realLineNumber);
                        lexemeBuilder.Clear();
                        continue;
                    }

                    if (Delimiters.Contains(symbol))
                    {
                        AddLexeme(symbol, realLineNumber);
                    }

                    lexemeBuilder.Clear();
                    continue;
                }

                if (!TrimDelimiters.Contains(symbol))
                {
                    lexemeBuilder.Append(symbol);
                }
            }

            return(new OuterLexemes()
            {
                Identifiers = Identifiers,
                Constants = Constants,
                Lexemes = Lexemes,
                Errors = Errors,
                Grammar = GrammarLexemes
            });
        }
예제 #3
0
        public void Parse()
        {
            Tokenizer.Tokenize(this);

            foreach (var us in UserSegments)
            {
                if (!us.Closed)
                {
                    us.OpenToken.ParentLexeme.Error = new Error(ErrorType.UnclosedSegment, us.OpenToken);
                }
                if (!us.Opened)
                {
                    us.CloseToken.ParentLexeme.Error = new Error(ErrorType.UnopenedSegment, us.CloseToken);
                }
            }

            // Replace EQUs
            foreach (var lexeme in Lexemes)
            {
                if (lexeme.Error == null)
                {
                    lexeme.ProceedEqu();
                    lexeme.Structure = lexeme.GetStructure();
                }
            }

            foreach (var lexeme in Lexemes)
            {
                if (lexeme.Error == null)
                {
                    if (!lexeme.HasLabel && lexeme.Structure.HasName && lexeme.Structure != null &&
                        lexeme.Structure.HasInstruction && lexeme.Tokens[lexeme.Structure.InstructionIndex].Type ==
                        TokenType.Instruction)
                    {
                        lexeme.Error = new Error(ErrorType.UnexpectedToken, lexeme.Tokens[0]);
                        continue;
                    }

                    if (!lexeme.HasLabel && lexeme.Structure != null && lexeme.Structure.HasName &&
                        !lexeme.Structure.HasInstruction)
                    {
                        lexeme.Error = new Error(ErrorType.UnexpectedToken, lexeme.Tokens[0]);
                        continue;
                    }

                    lexeme.AssignInlineUserSegmentsAndLabels(out var error);
                    if (error != null)
                    {
                        lexeme.Error = error;
                    }
                }
            }

            var lastLexeme = Lexemes.Last();

            if (lastLexeme.Tokens.Count != 1 ||
                lastLexeme.Tokens[0].Type != TokenType.EndKeyword)
            {
                lastLexeme.Error = new Error(ErrorType.MissingEndKeyword);
            }
        }
예제 #4
0
        private void ProceedConditionalDirectives()
        {
            var toDelete   = new List <int>();
            var openedIf   = false;
            var openedElse = false;
            var ifCond     = false;

            for (var i = 0; i < Lexemes.Count; i++)
            {
                var lexeme = Lexemes[i];
                if (lexeme.Error != null)
                {
                    continue;
                }

                if (lexeme.Tokens[0].Type == TokenType.IfDirective)
                {
                    if (openedIf || openedElse)
                    {
                        lexeme.Error = new Error(ErrorType.UnexpectedDirective, lexeme.Tokens[0]);
                        continue;
                    }

                    openedIf = true;

                    if (lexeme.Tokens.Count != 2)
                    {
                        lexeme.Error = new Error(ErrorType.WrongDirectiveFormat, lexeme.Tokens[0]);
                        continue;
                    }

                    var cond = lexeme.Tokens[1];
                    if (cond.IsNumber())
                    {
                        ifCond = cond.ToValue() != 0;
                    }

                    else
                    {
                        lexeme.Error = new Error(ErrorType.IncorrectInstructionTypes, lexeme.Tokens[0]);
                        continue;
                    }

                    toDelete.Add(i);
                }
                else if (lexeme.Tokens[0].Type == TokenType.ElseDirective)
                {
                    if (!openedIf)
                    {
                        lexeme.Error = new Error(ErrorType.UnexpectedDirective, lexeme.Tokens[0]);
                        continue;
                    }

                    openedIf   = false;
                    openedElse = true;

                    toDelete.Add(i);
                }
                else if (lexeme.Tokens[0].Type == TokenType.EndifDirective)
                {
                    if (!openedIf && !openedElse)
                    {
                        lexeme.Error = new Error(ErrorType.UnexpectedDirective, lexeme.Tokens[0]);
                        continue;
                    }

                    openedElse = false;
                    openedIf   = false;

                    toDelete.Add(i);
                }
                else
                {
                    if (openedIf && !ifCond)
                    {
                        toDelete.Add(i);
                    }
                    else if (openedElse && ifCond)
                    {
                        toDelete.Add(i);
                    }
                }
            }

            if (openedIf || openedElse)
            {
                var lastLexeme = Lexemes.Last();
                lastLexeme.Error = new Error(ErrorType.MissingEndKeyword);
            }

            toDelete.Reverse();
            foreach (var index in toDelete)
            {
                Lexemes.RemoveAt(index);
            }
        }