Пример #1
0
 /// <summary>
 ///		Parses ok, or throws
 /// </summary>
 /// <param name="terminatingCharacter">
 ///		Stops parsing if it sees this CodePoint in an unnested context.
 /// </param>
 /// <returns>
 ///		AbstractSyntaxTree representing parse, or throws
 /// </returns>
 public AbstractSyntaxTree Parse(CodePoint terminatingCharacter)
 {
     _operatorStack.Clear();
     _operatorStack.Push(Operator.None);                // make Peek () safe to do without first checking if empty
     _operandStack.Clear();
     return(ParseToResult(terminatingCharacter));
 }
Пример #2
0
 private void ReadIntoNext()
 {
     if (!_next.AtEOF())
     {
         _nextCursor++;
         _next = _cps.Read();
     }
 }
Пример #3
0
 private AbstractSyntaxTree ParseToResult(CodePoint terminatingCharacter)
 {
     ParseExpressionToStack(terminatingCharacter);
     while (_operatorStack.Peek() != Operator.None)
     {
         ReduceTopOperator();
     }
     if (_operandStack.Count != 1)
     {
         throw new AssertionFailedException("operand stack should have only 1 operand");
     }
     return(_operandStack.Pop());
 }
Пример #4
0
        /// <summary>
        ///		Attempts to parse.  Does not throw on error.
        /// </summary>
        /// <param name="terminatingCharacter">
        ///		Stops parsing if it sees this CodePoint in an unnested context.
        /// </param>
        /// <returns>
        ///		Either the result or a list of errors
        ///		(Could/should return list of warnings with results as well.)
        /// </returns>
        public ResultOrErrorList <AbstractSyntaxTree> TryParse(CodePoint terminatingCharacter)
        {
            _operatorStack.Clear();
            _operatorStack.Push(Operator.None);                 // make Peek () safe to do without first checking if empty
            _operandStack.Clear();

            try {
                return(new ResultOrErrorList <AbstractSyntaxTree> (ParseToResult(terminatingCharacter)));
            } catch (Exceptions.CompilationException p) {
                return(new ResultOrErrorList <AbstractSyntaxTree> (new List <Exceptions.CompilationException> ()
                {
                    p
                }));
            }
        }
Пример #5
0
        public void Advance()
        {
            if (!_curr.AtEOF(  ))
            {
                _cursor       = _nextCursor;
                _curr         = _next;
                _currLineMark = _nextLineMark;
                ReadIntoNext( );

                switch (_curr.Value)
                {
                case '\r':
                    _curr = new CodePoint(( byte )'\n');
                    if (_next.Value == '\n')
                    {
                        ReadIntoNext( );
                    }
                    goto case '\n';

                case '\n':
                    _line++;
                    _nextLineMark     = _nextCursor;
                    _indentationLevel = 0;
                    _nonBlankSeen     = false;
                    HandlePPDirectivesFromNormalMode( );
                    break;

                case ' ':
                    _indentationLevel++;
                    break;

                case '\t':
                    if ((_indentationLevel & 7) != 0)
                    {
                        throw new CompilationException("tab after space is illegal for indentation");
                    }
                    _indentationLevel += 8;                             // tab level
                    break;

                default:
                    _nonBlankSeen = true;
                    break;
                }
            }
        }
Пример #6
0
        private readonly CodePoint [] _idMores  = { new CodePoint((byte)'_'), new CodePoint((byte)'.') };                //, new CodePoint ( (byte) '-' ) };

        public ScanIt(CodePointStream cps, string job, System.IO.TextWriter lg)
        {
            _defdDict = new HashSet <ByteString> {
                new ByteString("true"), new ByteString("1")
            };

            _cps  = cps;
            _job  = job;
            _lg   = lg;
            _line = 0;
            _currTokenCursorStart = _cursor = _currLineMark = -2;
            _nextCursor           = _nextLineMark = -1;
            _indentationLevel     = 0;
            _tokenModeStack       = new Stack <TokenModeEnum> ();
            PushMode(TokenModeEnum.Illegal);
            PushMode(TokenModeEnum.Normal);
            _curr = new CodePoint((byte)' ');
            _next = new CodePoint((byte)'\n');
            Advance();
            Advance();
        }
Пример #7
0
        private void ParseExpressionToStack(CodePoint terminatingCharacter)
        {
            for ( ; ;)                  // Alternate between the States
            {
                // initial State: Unary State
                for ( ; ;)                  // Unary State
                {
                    var token = _scanner.Token();

                    switch (token.Value)
                    {
                    case '(':
                        _scanner.Advance();
                        _operatorStack.Push(Operator
                                            .PrecedenceGroupingParenthesis);              // nothing to reduce, as '(' has highest precedence
                        continue;

                    case ')':
                        _scanner.Advance();
                        if (_operatorStack.Peek() != Operator.FunctionCall)
                        {
                            _scanner.ErrorAtMark("unexpected ) in unary state");
                        }
                        _operatorStack.Pop();
                        // NB: We have a function call with no argument list, and we can either:
                        //	provide a unary function call operator
                        //		but our automated operator generators don't have that concept, or,
                        //  push an empty operand onto the stack so there's two operands for it to work
                        _operandStack.Push(null);
                        BuildAndPushOperator(Operator.FunctionCall);
                        break;

                    case '!':
                        _scanner.Advance();
                        _operatorStack.Push(Operator.LogicalNot);                            // prefix unary operators have implicit highest precedence
                        continue;

                    case '&':
                        _scanner.Advance();
                        _operatorStack.Push(Operator.AddressOf);
                        continue;

                    case '*':
                        _scanner.Advance();
                        _operatorStack.Push(Operator.Indirection);
                        continue;

                    case '+':
                        _scanner.Advance();
                        ReduceAndPushByChoice('+', Operator.PrefixIncrement, Operator.FixPoint);
                        continue;

                    case '-':
                        _scanner.Advance();
                        ReduceAndPushByChoice('-', Operator.PrefixDecrement, Operator.Negation);
                        continue;

                    case '~':
                        _scanner.Advance();
                        _operatorStack.Push(Operator.BitwiseComplement);
                        continue;

                    case 'A':
                        var id = _scanner.GetIdentifier();
                        // we can look up the variable in a symbol table here
                        _operandStack.Push(_symbolTable.LookupSymbol(id));
                        break;

                    case '0':
                        var num = _scanner.GetNonNegativeIntegralLiteral();
                        _operandStack.Push(new LongIntegerTreeNode(num));
                        break;

                    case '\"':
                        var str = _scanner.GetStringLiteral();
                        _operandStack.Push(new StringTreeNode(str));
                        break;

                    case '\'':
                        var chStr = _scanner.GetStringLiteral();
                        var cps   = new CodePointStream(chStr);
                        var cp1   = cps.Read();
                        if (cp1.AtEOF())
                        {
                            _scanner.ErrorAtMark("not enough characters in character literal");
                        }
                        var cp2 = cps.Read();
                        if (!cp2.AtEOF())
                        {
                            _scanner.ErrorAtMark("too many characters in character literal");
                        }
                        _operandStack.Push(new LongIntegerTreeNode(cp1.Value));
                        break;

                    default:
                        _scanner.ErrorAtMark("unrecognized token: " + (char)token.Value);
                        return;
                    }

                    break;        // switch to Binary State
                }                 // for (;;) { end of Unary State

                for ( ; ;)        // Binary State
                {
                    var cp = _scanner.Token();
                    if (cp.AtEOF() || cp == terminatingCharacter && AtTopLevelAndUnblocked())
                    {
                        return;
                    }

                    switch (cp.Value)
                    {
                    case '(':
                        _scanner.Advance();
                        ReduceThenPushOperator(Operator.FunctionCall);
                        break;

                    case ',':
                        _scanner.Advance();
                        AcceptComma();
                        break;

                    case ')':
                        _scanner.Advance();
                        AcceptCloseParen();
                        continue;                         // stay in Binary State

                    case '[':
                        _scanner.Advance();
                        ReduceThenPushOperator(Operator.Subscript);
                        break;

                    case ']':
                        _scanner.Advance();
                        // we have a [ b ], so we reduce until we reach the '['
                        ReduceUntilMatch(Operator.Subscript);
                        // reduction pops the operator, and, leaves us with a & b on the operand stack
                        BuildAndPushOperator(Operator.Subscript);
                        continue;                         // stay in Binary State

                    case '!':
                        _scanner.Advance();
                        if (!_scanner.IfCharacter('='))
                        {
                            _scanner.ErrorAtMark("expected = for !=");
                        }
                        ReduceThenPushOperator(Operator.NotEqual);
                        break;

                    case '*':
                        _scanner.Advance();
                        ReduceAndPushByChoice('=', Operator.AssignmentMultiplication, Operator.Multiplication);
                        break;

                    case '/':
                        _scanner.Advance();
                        ReduceAndPushByChoice('=', Operator.AssignmentDivision, Operator.Division);
                        break;

                    case '%':
                        _scanner.Advance();
                        ReduceAndPushByChoice('=', Operator.AssignmentModulo, Operator.Modulo);
                        break;

                    case '=':
                        _scanner.Advance();
                        ReduceAndPushByChoice('=', Operator.EqualEqual, Operator.Assignment);
                        break;

                    case '^':
                        _scanner.Advance();
                        ReduceAndPushByChoice('=', Operator.AssignmentBitwiseXor, Operator.BitwiseXor);
                        break;

                    case '+':
                        _scanner.Advance();
                        if (_scanner.IfCharacter('+'))
                        {
                            // C/C++ postfix ++
                            ReduceThenPushOperator(Operator.PostfixIncrement);
                            continue;                             // stay in Binary State
                        }

                        ReduceAndPushByChoice('=', Operator.AssignmentAddition, Operator.Addition);
                        break;

                    case '-':
                        _scanner.Advance();
                        if (_scanner.IfCharacter('>'))
                        {
                            // at least ->
                            if (_scanner.IfCharacter('*'))
                            {
                                // C++: member pointer: ->*
                                // ToDo: parse rhs of ->* (which is a member name) and generate an binary node to push on the operand stack
                                throw new System.NotImplementedException("->*");
                            }
                            else
                            {
                                // C/C++ indirect selection: ->
                                var memberName = _scanner.ExpectIdentifier("member identifier");
                                // ToDo: parse rhs of -> (which is a member name) and generate an operand to push on
                                throw new System.NotImplementedException("->");
                            }
                        }
                        else
                        {
                            ReduceAndPushByChoice('-', Operator.PostfixDecrement, '=', Operator.AssignmentSubtraction,
                                                  Operator.Subtraction);
                        }

                        break;

                    case '&':
                        _scanner.Advance();
                        ReduceAndPushByChoice('&', Operator.ShortCircutAnd, '=', Operator.AssignmentBitwiseAnd, Operator.BitwiseAnd);
                        break;

                    case '|':
                        _scanner.Advance();
                        ReduceAndPushByChoice('|', Operator.ShortCircutOr, '=', Operator.AssignmentBitwiseOr, Operator.BitwiseOr);
                        break;

                    case '.':
                        throw new System.NotImplementedException(". operator");

                    case '?':
                        _scanner.Advance();
                        // Operator.TernaryTest is used for grouping of the expressions during parsing,
                        //	This operator won't appear in the final tree (similar to Operator.GroupingParen which doesn't appear in the abstract tree either)
                        ReduceThenPushOperator(Operator.TernaryTest);
                        // Test 1003: a?b,c:d, which should parse ok as:
                        ////			a?(b,c):d
                        ////			   -and not-
                        ////			(a?b),(c:d)
                        ////			   as this makes no sense and thus is not helpful
                        break;

                    case ':':
                        _scanner.Advance();
                        if (_scanner.IfCharacter(':'))
                        {
                            throw new System.NotImplementedException(":: operator");
                        }
                        else
                        {
                            ReduceUntilMatch(Operator.TernaryTest);
                            // this will leave two operands on the stack, so for
                            //		a ? b :			-- which is what we have so far
                            //	a and b will be on the operand stack.
                            // now we push the true ternary operator:
                            _operatorStack.Push(Operator.TernaryChoice);
                            // when it gets reduced later, so for
                            //		a ? b : c;
                            // reducing this operator will consume a, b, and c.
                        }
                        break;

                    case '<':
                        _scanner.Advance();
                        ReduceAndPushByChoice('<', '=', Operator.AssignmentBitwiseLeftShift, Operator.BitwiseLeftShift, '=',
                                              Operator.LessOrEqual, Operator.LessThan);
                        break;

                    case '>':
                        _scanner.Advance();
                        ReduceAndPushByChoice('>', '=', Operator.AssignmentBitwiseRightShift, Operator.BitwiseRightShift, '=',
                                              Operator.GreaterOrEqual, Operator.GreaterThan);
                        break;

                    default:
                        return;                         // let caller deal with the "unexpected" input, like ;
                    }

                    break;  // switch to Unary State
                }           // end of for (;;) { Binary State
            }               // end of for(;;) { Alternating between the states
        }