public static Expression ParseLambda(TokenStream tokens) { tokens.SkipWhitespace(); if (tokens.IsNext("lambda")) { Token lambdaToken = tokens.PopExpected("lambda"); List<Token> argNames = new List<Token>(); List<Expression> argValues = new List<Expression>(); if (!tokens.PopIfPresent(":")) { bool nextAllowed = true; while (!tokens.PopIfPresent(":")) { if (!nextAllowed) tokens.PopExpected(":"); // throws Token argName = tokens.Pop(); if (!Util.IsIdentifier(argName)) throw new ParserException(argName, "Invalid lambda arg name."); Expression argValue = null; if (tokens.PopIfPresent("=")) { argValue = ExpressionParser.Parse(tokens); } argNames.Add(argName); argValues.Add(argValue); nextAllowed = tokens.PopIfPresent(","); } } } return ParseTernary(tokens); }
private Executable ParseImport(TokenStream tokens, int indention) { tokens.SkipWhitespace(); List<Token> fromChain = null; List<Token> importChain = null; List<Token> asChain = null; Token firstToken = null; if (tokens.PeekValue() == "from") { firstToken = tokens.Pop(); fromChain = ParseDotChainForImport(tokens); } firstToken = firstToken ?? tokens.PopExpected("import"); importChain = ParseDotChainForImport(tokens); if (tokens.PopIfPresent("as")) { asChain = ParseDotChainForImport(tokens); if (asChain.Count > 1) throw new ParserException(asChain[0], "Expected: variable"); } return new ImportStatement(firstToken, importChain, fromChain, asChain == null ? null : asChain[0]); }
private Executable ParseAtomicItem(TokenStream tokens, int indention) { tokens.SkipWhitespace(); Token token = tokens.Pop(); if (token.Value == "break") return new BreakStatement(token); if (token.Value == "continue") return new ContinueStatement(token); if (token.Value == "pass") return new PassStatement(token); throw new Exception("wat?"); }
public static Expression ParseBooleanAnd(TokenStream tokens) { tokens.SkipWhitespace(); Expression left = ParseBooleanNot(tokens); if (tokens.PopIfPresent("and")) { Expression right = ParseBooleanAnd(tokens); return new BooleanCombinator(left, right, "and"); } return left; }
// YOU LEFT OFF HERE // You were about to go through and document exactly what each indention variable meant more clearly. private IList<Executable> ParseBlock(TokenStream tokens, int ownerIndention, bool start) { int blockIndention = tokens.PeekIndention(); if (start) { if (blockIndention != 0) { throw new ParserException(tokens.Peek(), "Unexpected indention"); } } else { if (blockIndention == -1) { // This indicates the code is on the same line. Parse one line. // def foo(): return 42 Executable exec = this.Parse(tokens, false, -1); return new List<Executable>() { exec }; } if (blockIndention <= ownerIndention) { // No indention was found. But it is required. throw new ParserException(tokens.Peek(), "Expected: indention"); } } int requiredIndention = blockIndention; List<Executable> code = new List<Executable>(); while (tokens.HasMore) { int currentIndention = tokens.PeekIndention(); // any new indention should be handled by a recursive call if (currentIndention > requiredIndention) throw new ParserException(tokens.Peek(), "Unexpected indention"); // if it's indented less than the required but more than the previous, then that's not right // e.g. // def foo() // x = 1 // return x # this is wrong if (currentIndention < requiredIndention && currentIndention > ownerIndention) throw new ParserException(tokens.Peek(), "Unexpected indention"); // def foo() // x = 42 // y = 3.14 # this is no longer part of foo() // start is excluded because when start is true, the owner indention and current indention are the same. if (!start && currentIndention <= ownerIndention) return code; tokens.SkipWhitespace(); if (tokens.HasMore) { code.Add(this.Parse(tokens, true, currentIndention)); } else { return code; } } return code; }
private Executable ParseReturn(TokenStream tokens, int indention) { tokens.SkipWhitespace(); Token token = tokens.PopExpected("return"); Expression value = null; if (tokens.HasMore && tokens.PeekType() != TokenType.NEWLINE) { value = ExpressionParser.Parse(tokens); } return new ReturnStatement(token, value); }
private static Expression ParseRootEntity(TokenStream tokens) { tokens.SkipWhitespace(); string next = tokens.PeekValue(); if (next == "True" || next == "False") { Token token = tokens.Pop(); return new BooleanConstant(token, next == "True"); } else if (next == "None") { Token token = tokens.Pop(); return new NullConstant(token); } else if (next.StartsWith("'") || next.StartsWith("\"")) { Token token = tokens.Pop(); int quoteSize = next.StartsWith("'''") || next.StartsWith("\"\"\"") ? 3 : 1; return new StringConstant(token, Util.RemoveEscapeSequences(token, next.Substring(quoteSize, next.Length - quoteSize * 2))); } else if (next.StartsWith("r'") || next.StartsWith("r\"")) { Token token = tokens.Pop(); int quoteSize = next.StartsWith("r'''") || next.StartsWith("r\"\"\"") ? 3 : 1; return new StringConstant(token, next.Substring(quoteSize + 1, next.Length - quoteSize * 2 - 1)); } else if (next == "(") { // Tuples or parentehsis Token parenthesisToken = tokens.Pop(); List<Expression> parenthesisExpressions = new List<Expression>(); bool nextAllowed = true; while (!tokens.PopIfPresent(")")) { if (!nextAllowed) tokens.PopExpected(")"); // throws parenthesisExpressions.Add(Parse(tokens)); nextAllowed = tokens.PopIfPresent(","); tokens.SkipWhitespace(); } if (parenthesisExpressions.Count > 1 || nextAllowed) { return new InlineTuple(parenthesisToken, parenthesisExpressions); } else { return new ParenthesisGroup(parenthesisToken, parenthesisExpressions[0]); } } else if (next == "[") { Token bracketToken = tokens.Pop(); List<Expression> listItems = new List<Expression>(); bool nextAllowed = true; while (!tokens.PopIfPresent("]")) { if (!nextAllowed) tokens.PopExpected("]"); // throws listItems.Add(Parse(tokens)); nextAllowed = tokens.PopIfPresent(","); tokens.SkipWhitespace(); } return new InlineList(bracketToken, listItems); } else if (next == "{") { Token braceToken = tokens.Pop(); List<Expression> dictionaryKeys = new List<Expression>(); List<Expression> dictionaryValues = new List<Expression>(); bool nextAllowed = true; while (!tokens.PopIfPresent("}")) { if (!nextAllowed) tokens.PopExpected("}"); // throws dictionaryKeys.Add(Parse(tokens)); tokens.PopExpected(":"); dictionaryValues.Add(Parse(tokens)); nextAllowed = tokens.PopIfPresent(","); tokens.SkipWhitespace(); } return new InlineDictionary(braceToken, dictionaryKeys, dictionaryValues); } else if (next.StartsWith("0x") || next.StartsWith("0o") || next.StartsWith("0X") || next.StartsWith("0O")) { Token integerToken = tokens.Pop(); int radix = next.ToLowerInvariant().StartsWith("0x") ? 16 : 8; string stringValue = next.Substring(2); if (stringValue.Length == 0) { throw new ParserException(integerToken, "Invalid base " + radix + " constant."); } int value = Util.ParseNumber(integerToken, stringValue, radix); return new IntegerConstant(integerToken, value); } else if (next[0] >= '0' && next[0] <= '9') { Token numberToken = tokens.Pop(); if (next.Contains('.') || next.Contains('e') || next.Contains('E')) { double value = Util.ParseDouble(numberToken); return new FloatConstant(numberToken, value); } else { int value = Util.ParseNumber(numberToken, next, 10); return new IntegerConstant(numberToken, value); } } else if (next[0] == '.') { Token numberToken = tokens.Pop(); double value = Util.ParseDouble(numberToken); return new FloatConstant(numberToken, value); } else if (next[0] == '$') { // Because system functions can't be used as pointers, the invocation and arguments // are parsed here. Any standalone occurence of a system function is an error. Token dollarToken = tokens.Pop(); Token nameToken = tokens.Pop(); if (!Util.IsIdentifier(nameToken)) throw new ParserException(nameToken, "Invalid system function name."); tokens.PopExpected("("); bool nextAllowed = true; List<Expression> args = new List<Expression>(); while (!tokens.PopIfPresent(")")) { args.Add(Parse(tokens)); nextAllowed = tokens.PopIfPresent(","); } return new SystemFunctionInvocation(dollarToken, nameToken, args); } else if ( (next[0] >= 'a' && next[0] <= 'z') || (next[0] >= 'A' && next[0] <= 'Z') || next[0] == '_') { Token token = tokens.Pop(); return new Variable(token, token.Value); } else { throw new ParserException(tokens.Peek(), "Unrecognized token."); } }
private static Expression ParseNot(TokenStream tokens) { tokens.SkipWhitespace(); string next = tokens.PeekValue(); if (next == "+" || next == "-" || next == "~") { Token token = tokens.Pop(); Expression root = ParseExponents(tokens); return new Negation(token, root, token.Value == "+" ? Negation.PrefixType.POSITIVE : token.Value == "-" ? Negation.PrefixType.NEGATIVE : Negation.PrefixType.BITWISE_NOT); } return ParseExponents(tokens); }
public static Expression ParseBooleanNot(TokenStream tokens) { tokens.SkipWhitespace(); if (tokens.IsNext("not")) { Token notToken = tokens.Pop(); Expression expression = ParseComparisons(tokens); return new Negation(notToken, expression, Negation.PrefixType.BOOLEAN_NOT); } return ParseComparisons(tokens); }