private void ParseLines(SimpleCircuitLexer lexer, Circuit ckt) { do { ParseLine(lexer, ckt); if (!lexer.Is(TokenType.Newline) && !lexer.Is(TokenType.EndOfContent)) { throw new ParseException($"Expected a new line", lexer.Line, lexer.Position); } while (lexer.Is(TokenType.Newline)) { lexer.Next(); } }while (!lexer.Is(TokenType.EndOfContent)); }
private List <WireDescription> ParseWire(SimpleCircuitLexer lexer) { var wires = new List <WireDescription>(); lexer.Check(TokenType.OpenBracket, "<"); do { var direction = ParseDirection(lexer); wires.Add(new WireDescription { Direction = direction, Length = -1.0 }); if (lexer.Is(TokenType.Number)) { wires[wires.Count - 1].Length = double.Parse(lexer.Content, System.Globalization.CultureInfo.InvariantCulture); lexer.Next(); } }while (!lexer.Is(TokenType.CloseBracket, ">")); lexer.Next(); return(wires); }
private string ParseDirection(SimpleCircuitLexer lexer) { if (lexer.Is(TokenType.Word)) { switch (lexer.Content) { case "u": case "d": case "l": case "r": var dir = lexer.Content; lexer.Next(); return(dir); } } if (lexer.Is(TokenType.Question)) { lexer.Next(); return("?"); } throw new ParseException($"Expected a direction", lexer.Line, lexer.Position); }
private void ParseLine(SimpleCircuitLexer lexer, Circuit ckt) { if (lexer.Is(TokenType.Newline)) { return; } else if (lexer.Is(TokenType.Dash)) { ParseEquation(lexer, ckt); } else if (lexer.Is(TokenType.Dot)) { ParseOption(lexer, ckt); } else if (lexer.Is(TokenType.Word)) { ParseChain(lexer, ckt); } else { throw new ParseException($"Could not read {lexer.Content}", lexer.Line, lexer.Position); } }
private IComponent ParseComponentLabel(SimpleCircuitLexer lexer, Circuit ckt) { var component = GetComponent(ParseName(lexer), ckt); if (lexer.Is(TokenType.OpenBracket, "(")) { lexer.Next(); var label = ParseLabel(lexer); if (component is ILabeled lbl) { lbl.Label = label; } lexer.Check(TokenType.CloseBracket, ")"); } return(component); }
private PinDescription ParsePin(SimpleCircuitLexer lexer, Circuit ckt) { var result = new PinDescription(); result.ComponentName = lexer.Content; result.Component = ParseComponentLabel(lexer, ckt); if (lexer.Is(TokenType.OpenBracket, "[")) { lexer.Next(); var pin = ParseName(lexer); lexer.Check(TokenType.CloseBracket, "]"); result.AfterName = pin; result.After = (TranslatingPin)result.Component.Pins[pin]; } return(result); }
private void ParseEquation(SimpleCircuitLexer lexer, Circuit ckt) { if (!lexer.Is(TokenType.Dash)) { throw new ParseException($"A dash was expected", lexer.Line, lexer.Position); } lexer.Next(); // Add the first equation var a = ParseSum(lexer, ckt); lexer.Check(TokenType.Equals); var b = ParseSum(lexer, ckt); if (a is Function fa && b is Function fb) { ckt.Add(fa - fb, $"keep {fa} and {fb} equal"); }
private PinDescription ParseDoublePin(SimpleCircuitLexer lexer, Circuit ckt) { string beforePin = null; if (lexer.Is(TokenType.OpenBracket, "[")) { lexer.Next(); beforePin = ParseName(lexer); lexer.Check(TokenType.CloseBracket, "]"); } var result = ParsePin(lexer, ckt); if (beforePin != null) { result.BeforeName = beforePin; result.Before = (TranslatingPin)result.Component.Pins[beforePin]; } return(result); }
private void ParseChain(SimpleCircuitLexer lexer, Circuit ckt) { var start = ParsePin(lexer, ckt); PinDescription end = null; while (lexer.Is(TokenType.OpenBracket)) { if (start.Component is Point pts) { pts.Wires++; } var wires = ParseWire(lexer); end = ParseDoublePin(lexer, ckt); // String them together var lastPin = start.After ?? (TranslatingPin)start.Component.Pins.Last(p => p is TranslatingPin); var wire = new Wire(lastPin); ckt.Add(wire); for (var i = 0; i < wires.Count; i++) { TranslatingPin nextPin; if (i < wires.Count - 1) { var pt = new Point("X:" + (_anonIndex++)); ckt.Add(pt); nextPin = (TranslatingPin)pt.Pins.First(p => p is TranslatingPin); pt.Wires += 2; } else { nextPin = end.Before ?? (TranslatingPin)end.Component.Pins.First(p => p is TranslatingPin); if (end.Component is Point pte) { pte.Wires++; } } // Create a new segment for our wire var length = new Unknown($"W{++_wireIndex}.Length", UnknownTypes.Length); wire.To(nextPin, length); var dir = wires[i].Direction.ToLower(); // Constrain the positions switch (dir) { case "u": ckt.Add(nextPin.X - lastPin.X, $"align {nextPin} with {lastPin} (line {lexer.Line})"); ckt.Add(lastPin.Y - nextPin.Y - length, $"define wire {length} (line {lexer.Line})"); break; case "d": ckt.Add(nextPin.X - lastPin.X, $"align {nextPin} with {lastPin} (line {lexer.Line})"); ckt.Add(nextPin.Y - lastPin.Y - length, $"define wire {length} (line {lexer.Line})"); break; case "l": ckt.Add(lastPin.X - nextPin.X - length, $"define wire {length} (line {lexer.Line})"); ckt.Add(lastPin.Y - nextPin.Y, $"align {nextPin} and {lastPin} (line {lexer.Line})"); break; case "r": ckt.Add(nextPin.X - lastPin.X - length, $"define wire {length} (line {lexer.Line})"); ckt.Add(lastPin.Y - nextPin.Y, $"align {nextPin} and {lastPin} (line {lexer.Line})"); break; } // Constrain the directions if (lastPin is IRotating rlastPin) { switch (dir) { case "u": ckt.Add(rlastPin.NormalY + 1, $"point {rlastPin} up (line {lexer.Line})"); ckt.Add(rlastPin.NormalX, $"point {rlastPin} up (line {lexer.Line})"); break; case "d": ckt.Add(rlastPin.NormalY - 1, $"point {rlastPin} down (line {lexer.Line})"); ckt.Add(rlastPin.NormalX, $"point {rlastPin} down (line {lexer.Line})"); break; case "l": ckt.Add(rlastPin.NormalY, $"point {rlastPin} left (line {lexer.Line})"); ckt.Add(rlastPin.NormalX + 1, $"point {rlastPin} left (line {lexer.Line})"); break; case "r": ckt.Add(rlastPin.NormalY, $"point {rlastPin} right (line {lexer.Line})"); ckt.Add(rlastPin.NormalX - 1, $"point {rlastPin} right (line {lexer.Line})"); break; case "?": ckt.Add(lastPin.X + rlastPin.NormalX * length - nextPin.X, $"point {rlastPin} to {nextPin} (line {lexer.Line})"); ckt.Add(lastPin.Y + rlastPin.NormalY * length - nextPin.Y, $"point {rlastPin} to {nextPin} (line {lexer.Line})"); break; } } if (nextPin is IRotating rnextPin) { switch (dir) { case "u": ckt.Add(rnextPin.NormalY - 1, $"point {rnextPin} up (line {lexer.Line})"); ckt.Add(rnextPin.NormalX, $"point {rnextPin} up (line {lexer.Line})"); break; case "d": ckt.Add(rnextPin.NormalY + 1, $"point {rnextPin} down (line {lexer.Line})"); ckt.Add(rnextPin.NormalX, $"point {rnextPin} down (line {lexer.Line})"); break; case "l": ckt.Add(rnextPin.NormalY, $"point {rnextPin} left (line {lexer.Line})"); ckt.Add(rnextPin.NormalX - 1, $"point {rnextPin} left (line {lexer.Line})"); break; case "r": ckt.Add(rnextPin.NormalY, $"point {rnextPin} right (line {lexer.Line})"); ckt.Add(rnextPin.NormalX + 1, $"point {rnextPin} right (line {lexer.Line})"); break; case "?": ckt.Add(nextPin.X + rnextPin.NormalX * length - lastPin.X, $"point {rnextPin} to {lastPin} (line {lexer.Line})"); ckt.Add(nextPin.Y + rnextPin.NormalY * length - lastPin.Y, $"point {rnextPin} to {lastPin} (line {lexer.Line})"); break; } } // Fix the wire length if necessary if (wires[i].Length >= 0) { ckt.Add(length - wires[i].Length, $"fix wire length {length} to {wires[i].Length} (line {lexer.Line})"); } lastPin = nextPin; } start = end; } if (end != null && end.AfterName != null) { if (end.BeforeName == null) { Warn(this, new WarningEventArgs($"Pin {end.AfterName} was specified at the end of line {lexer.Line}, but it isn't used. Did you mean \"[{end.AfterName}]{end.ComponentName}\" instead of \"{end.ComponentName}[{end.AfterName}]\"?")); } else { Warn(this, new WarningEventArgs($"Pin {end.AfterName} was specified at the end of line {lexer.Line}, but it isn't used.")); } } }