/*** * Precondition: tokens.Current.Type == TokenType.IDENTIFIER || MAYBE_MACRO * Postcondition: tokens.Current is fully reduced (i.e. not a macro, and not a definition) * Returns: true iff tokens was actually expanded. */ public bool ExpandIdentifier(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes) { bool ret = false; //Macros and Definitions. if (tokens.Current.Type == TokenType.MAYBE_MACRO && Macros.ContainsName(tokens.Current.Content)) { Token head = tokens.Current; tokens.MoveNext(); IList <IList <Token> > parameters = ParseMacroParamList(tokens); if (Macros.HasMacro(head.Content, parameters.Count)) { tokens.PrependEnumerator(Macros.GetMacro(head.Content, parameters.Count).ApplyMacro(head, parameters, scopes).GetEnumerator()); } else { Error(head.Location, System.String.Format("No overload of {0} with {1} parameters.", head.Content, parameters.Count)); } return(true); } else if (tokens.Current.Type == TokenType.MAYBE_MACRO) { Token head = tokens.Current; tokens.MoveNext(); tokens.PutBack(new Token(TokenType.IDENTIFIER, head.Location, head.Content)); return(true); } else if (Definitions.ContainsKey(tokens.Current.Content)) { Token head = tokens.Current; tokens.MoveNext(); tokens.PrependEnumerator(Definitions[head.Content].ApplyDefinition(head).GetEnumerator()); return(true); } return(ret); }
public Maybe <ILineNode> ParseLine(MergeableGenerator <Token> tokens, ImmutableStack <Closure> scopes) { if (IsIncluding) { if (tokens.Current.Type == TokenType.NEWLINE || tokens.Current.Type == TokenType.SEMICOLON) { tokens.MoveNext(); return(new Nothing <ILineNode>()); } head = tokens.Current; switch (head.Type) { case TokenType.IDENTIFIER: case TokenType.MAYBE_MACRO: if (ExpandIdentifier(tokens, scopes)) { return(ParseLine(tokens, scopes)); } else { tokens.MoveNext(); if (tokens.Current.Type == TokenType.COLON) { tokens.MoveNext(); if (scopes.Head.HasLocalLabel(head.Content)) { Warning(head.Location, "Label already in scope, ignoring: " + head.Content); //replacing: " + head.Content); } else if (!IsValidLabelName(head.Content)) { Error(head.Location, "Invalid label name " + head.Content + '.'); } else { scopes.Head.AddLabel(head.Content, CurrentOffset); } return(new Nothing <ILineNode>()); } else { tokens.PutBack(head); return(ParseStatement(tokens, scopes)); } } case TokenType.OPEN_BRACE: return(new Just <ILineNode>(ParseBlock(tokens, new ImmutableStack <Closure>(new Closure(), scopes)))); case TokenType.PREPROCESSOR_DIRECTIVE: return(ParsePreprocessor(tokens, scopes)); case TokenType.OPEN_BRACKET: Error(head.Location, "Unexpected list literal."); IgnoreRestOfLine(tokens); break; case TokenType.NUMBER: case TokenType.OPEN_PAREN: Error(head.Location, "Unexpected mathematical expression."); IgnoreRestOfLine(tokens); break; default: tokens.MoveNext(); Error(head.Location, System.String.Format("Unexpected token: {0}: {1}", head.Type, head.Content)); IgnoreRestOfLine(tokens); break; } return(new Nothing <ILineNode>()); } else { bool hasNext = true; while (tokens.Current.Type != TokenType.PREPROCESSOR_DIRECTIVE && (hasNext = tokens.MoveNext())) { ; } if (hasNext) { return(ParsePreprocessor(tokens, scopes)); } else { Error(null, System.String.Format("Missing {0} endif(s).", Inclusion.Count)); return(new Nothing <ILineNode>()); } } }