/// <summary> /// Parses a SimpleCircuit statement. /// </summary> /// <param name="lexer">The lexer.</param> /// <param name="context">The parsing context.</param> /// <returns>Returns <c>true</c> if the statement was parsed successfully; otherwise, <c>false</c>.</returns> private static bool ParseStatement(SimpleCircuitLexer lexer, ParsingContext context) { switch (lexer.Type) { case TokenType.Word: return(ParseComponentChainStatement(lexer, context, (IPin pinToWire, WireInfo wireInfo, IPin wireToPin) => StringWiresTogether(pinToWire, wireInfo, wireToPin, context))); case TokenType.Dot: lexer.Next(); return(ParseControlStatement(lexer, context)); case TokenType.OpenParenthesis: return(ParseVirtualChainStatement(lexer, context)); case TokenType.Dash: return(ParsePropertyAssignmentStatement(lexer, context)); case TokenType.Newline: lexer.Next(); return(true); case TokenType.EndOfContent: return(true); default: context.Diagnostics?.Post(new TokenDiagnosticMessage(lexer.Token, SeverityLevel.Error, "PE001", $"Unrecognized {lexer.Content}")); lexer.Next(); return(false); } }
/// <summary> /// Parses SimpleCircuit code. /// </summary> /// <param name="lexer">The lexer.</param> /// <param name="context">The context.</param> public static void Parse(SimpleCircuitLexer lexer, ParsingContext context) { // Read until the end while (lexer.Type != TokenType.EndOfContent) { if (!ParseStatement(lexer, context)) { lexer.Skip(~TokenType.Newline); } } }
/// <summary> /// Parses a chain of components. /// </summary> /// <param name="lexer">The lexer.</param> /// <param name="context">The parsing context.</param> /// <param name="stringTogether">The action that is executed when wires should be </param> /// <returns>Returns <c>true</c> if the statement was parsed successfully; otherwise, <c>false</c>.</returns> private static bool ParseComponentChainStatement(SimpleCircuitLexer lexer, ParsingContext context, Action <IPin, WireInfo, IPin> stringTogether) { // component[pin] '<' wires '>' [pin]component[pin] '<' wires '>' ... '>' [pin]component var component = ParseComponent(lexer, context); if (component == null) { return(false); } Token pinName; // Parse wires while (lexer.Check(TokenType.OpenIndex | TokenType.OpenBeak)) { IPin pinToWire = null; // Read a pin if (lexer.Check(TokenType.OpenIndex)) { pinName = ParsePin(lexer, context); if (pinName.Content.Length == 0) { return(false); } if (!component.Pins.TryGetValue(pinName.Content.ToString().Trim(), out pinToWire)) { if (context.Diagnostics?.Post(pinName, ErrorCodes.CannotFindPin, pinName.Content.ToString(), component.Name) == SeverityLevel.Error) { return(false); } } } else if (component.Pins.Count == 0) { if (context.Diagnostics?.Post(lexer.StartToken, ErrorCodes.DoesNotHavePins, component.Name) == SeverityLevel.Error) { return(false); } } else { // Select the last pin pinToWire = component.Pins[^ 1];