private static int LengthToEndOfLine(CodePointStream cps) { int lineLength = 0; for ( ; ;) { var cp = cps.Read(); if (cp.Value == '\r' || cp.Value == '\n' || cp.AtEOF()) { break; } lineLength++; } return(lineLength); }
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(); }
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 }