private Ast AssignmentExpression() { Func <Ast> declaration = () => { if (!IsType(_tokenStream.Current)) { return(null); } Ast decl = Declaration(); AssignmentToken assignment = _tokenStream.Take <AssignmentToken>(); Ast expr = Expression(); return(new BinaryExpression(decl, assignment, expr)); }; Func <Ast> reAssignment = () => { if (!_tokenStream.IsMatch <IdentifierToken>()) { return(null); } Variable var = new Variable(_tokenStream.Take <IdentifierToken>()); AssignmentToken assignment = _tokenStream.Take <AssignmentToken>(); Ast expr = Expression(); return(new BinaryExpression(var, assignment, expr)); }; return (_tokenStream.Capture(declaration) ?? _tokenStream.Capture(reAssignment) ?? _tokenStream.Capture(LogicalOrExpression)); }
public override SemanticPayload Visit(AssignmentToken token, SemanticPayload payload) { return(Visit(token.Item2, payload) .Combine(new SemanticPayload { Contour = new Contour <None>(token.Item1, None.New()) })); }
/// <summary> /// Read the parameter /// </summary> /// <param name="st"></param> /// <param name="netlist"></param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { // Read all assignments for (int i = 0; i < st.Parameters.Count; i++) { switch (st.Parameters[i].kind) { case ASSIGNMENT: AssignmentToken at = st.Parameters[i] as AssignmentToken; switch (at.Name.kind) { case WORD: netlist.Path.Parameters.Add(new CircuitIdentifier(at.Name.image), netlist.ParseDouble(at.Value)); break; default: throw new ParseException(at.Name, "Parameter expected"); } break; default: throw new ParseException(st.Parameters[i], "Assignment expected"); } } Generated = null; return(true); }
/// <summary> /// Generate a capacitor /// </summary> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> protected ICircuitObject GenerateCap(CircuitIdentifier name, List <Token> parameters, Netlist netlist) { Capacitor cap = new Capacitor(name); cap.ReadNodes(netlist.Path, parameters); // Search for a parameter IC, which is common for both types of capacitors for (int i = 3; i < parameters.Count; i++) { if (parameters[i].kind == ASSIGNMENT) { AssignmentToken at = parameters[i] as AssignmentToken; if (at.Name.image.ToLower() == "ic") { double ic = netlist.ParseDouble(at.Value); cap.CAPinitCond.Set(ic); parameters.RemoveAt(i); break; } } } // The rest is just dependent on the number of parameters if (parameters.Count == 3) { cap.CAPcapac.Set(netlist.ParseDouble(parameters[2])); } else { cap.SetModel(netlist.FindModel <CapacitorModel>(parameters[2])); switch (parameters[2].kind) { case WORD: case IDENTIFIER: cap.SetModel(netlist.Path.FindModel <CapacitorModel>(netlist.Circuit.Objects, new CircuitIdentifier(parameters[2].image))); break; default: throw new ParseException(parameters[2], "Model name expected"); } netlist.ReadParameters(cap, parameters, 2); if (!cap.CAPlength.Given) { throw new ParseException(parameters[1], "L needs to be specified", false); } } return(cap); }
protected T Visit(IToken token, T state = default) { return(token switch { AddToken addToken => Visit(addToken, state), SubtractToken subtractToken => Visit(subtractToken, state), MultiplyToken multiplyToken => Visit(multiplyToken, state), DivideToken divideToken => Visit(divideToken, state), NegateToken negateToken => Visit(negateToken, state), NumberToken numberToken => Visit(numberToken, state), FactorialToken factorialToken => Visit(factorialToken, state), PowerToken powerToken => Visit(powerToken, state), VariableToken variableToken => Visit(variableToken, state), AssignmentToken assignmentToken => Visit(assignmentToken, state), _ => throw new ArgumentOutOfRangeException(nameof(token)) });
/// <summary> /// Read /// </summary> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { // Only assignments are possible for (int i = 0; i < st.Parameters.Count; i++) { switch (st.Parameters[i].kind) { case ASSIGNMENT: AssignmentToken at = st.Parameters[i] as AssignmentToken; switch (at.Name.kind) { case BRACKET: BracketToken bt = at.Name as BracketToken; if (bt.Name.image.ToLower() == "v" && bt.Parameters.Length == 1 && ReaderExtension.IsNode(bt.Parameters[0])) { netlist.Circuit.Nodes.Nodeset.Add(new CircuitIdentifier(bt.Parameters[0].image), netlist.ParseDouble(at.Value)); } else { throw new ParseException(st.Parameters[i], "Invalid format, v(<node>)=<ic> expected"); } break; default: if (ReaderExtension.IsNode(at.Name)) { netlist.Circuit.Nodes.Nodeset.Add(new CircuitIdentifier(at.Name.image), netlist.ParseDouble(at.Value)); } else { throw new ParseException(st.Parameters[i], "Invalid format, <node>=<ic> expected"); } break; } break; } } return(true); }
/// <summary> /// Read named parameters for a Parameterized object /// </summary> /// <param name="obj">The parameterized object</param> /// <param name="parameters">The parameters</param> /// <param name="start">The starting index</param> public static void ReadParameters(this Netlist netlist, IParameterized obj, List <Token> parameters, int start = 0) { for (int i = start; i < parameters.Count; i++) { if (parameters[i].kind == TokenConstants.ASSIGNMENT) { AssignmentToken at = parameters[i] as AssignmentToken; string pname; if (at.Name.kind == WORD) { pname = at.Name.image.ToLower(); } else { throw new ParseException(parameters[i], "Invalid assignment"); } switch (at.Value.kind) { case VALUE: obj.Set(pname, netlist.Readers.ParseDouble(at.Value.image.ToLower())); break; case EXPRESSION: obj.Set(pname, netlist.Readers.ParseDouble(at.Value.image.Substring(1, at.Value.image.Length - 2).ToLower())); break; case WORD: case STRING: obj.Set(pname, netlist.ParseString(at.Value)); break; default: throw new ParseException(parameters[i], "Invalid assignment"); } } } }
public virtual T Visit(AssignmentToken token, T state = default) { return(Visit(token.Item2, state ?? new T())); }
/// <summary> /// Read /// </summary> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { // Read all options for (int i = 0; i < st.Parameters.Count; i++) { switch (st.Parameters[i].kind) { case ASSIGNMENT: AssignmentToken at = st.Parameters[i] as AssignmentToken; string key = at.Name.image.ToLower(); switch (key) { case "abstol": SimulationConfiguration.Default.AbsTol = netlist.ParseDouble(at.Value); break; case "reltol": SimulationConfiguration.Default.RelTol = netlist.ParseDouble(at.Value); break; case "gmin": SimulationConfiguration.Default.Gmin = netlist.ParseDouble(at.Value); break; case "itl1": SimulationConfiguration.Default.DcMaxIterations = (int)Math.Round(netlist.ParseDouble(at.Value)); break; case "itl2": SimulationConfiguration.Default.SweepMaxIterations = (int)Math.Round(netlist.ParseDouble(at.Value)); break; case "itl4": SimulationConfiguration.Default.TranMaxIterations = (int)Math.Round(netlist.ParseDouble(at.Value)); break; case "temp": netlist.Circuit.State.Temperature = netlist.ParseDouble(at.Value) + Circuit.CONSTCtoK; break; case "tnom": netlist.Circuit.State.NominalTemperature = netlist.ParseDouble(at.Value) + Circuit.CONSTCtoK; break; case "method": switch (at.Value.image.ToLower()) { case "trap": case "trapezoidal": SimulationConfiguration.Default.Method = new IntegrationMethods.Trapezoidal(); break; } break; default: throw new ParseException(st.Parameters[i], "Unrecognized option"); } break; case WORD: key = st.Parameters[i].image.ToLower(); switch (key) { case "keepopinfo": SimulationConfiguration.Default.KeepOpInfo = true; break; default: throw new ParseException(st.Parameters[i], "Unrecognized option"); } break; default: throw new ParseException(st.Parameters[i], "Unrecognized option"); } } return(true); }
/// <summary> /// Generate a diode /// </summary> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> protected override ICircuitObject Generate(string type, CircuitIdentifier name, List <Token> parameters, Netlist netlist) { Diode dio = new Diode(name); dio.ReadNodes(netlist.Path, parameters); if (parameters.Count < 3) { throw new ParseException(parameters[1], "Model expected", false); } dio.SetModel(netlist.FindModel <DiodeModel>(parameters[2])); // Read the rest of the parameters for (int i = 3; i < parameters.Count; i++) { switch (parameters[i].kind) { case WORD: switch (parameters[i].image.ToLower()) { case "on": dio.DIOoff = false; break; case "off": dio.DIOoff = true; break; default: throw new ParseException(parameters[i], "ON or OFF expected"); } break; case ASSIGNMENT: AssignmentToken at = parameters[i] as AssignmentToken; if (at.Name.image.ToLower() == "ic") { dio.DIOinitCond = netlist.ParseDouble(at.Value); } else { throw new ParseException(parameters[i], "IC expected"); } break; case VALUE: case EXPRESSION: if (!dio.DIOarea.Given) { dio.DIOarea.Set(netlist.ParseDouble(parameters[i])); } else if (!dio.DIOtemp.Given) { dio.DIO_TEMP = netlist.ParseDouble(parameters[i]); } else { throw new ParseException(parameters[i], "Invalid parameter"); } break; default: throw new ParseException(parameters[i], "Unrecognized parameter"); } } return(dio); }
public override CodeGenPayload Visit(AssignmentToken token, CodeGenPayload state = default) { return(state?.Combine(new CodeGenPayload { Contour = new Contour <CodeGenPayload>(token.Item1, Visit(token.Item2, state)) })); }
/// <summary> /// Read subcircuit definitions /// </summary> /// <param name="name">Name</param> /// <param name="parameters">Parameters</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { if (st.Parameters.Count < 2) { throw new ParseException(st.Name, "Subcircuit name expected", false); } // Create the identifier of the subcircuit definition CircuitIdentifier name = new CircuitIdentifier(st.Parameters[0].image); if (netlist.Path.DefinitionPath != null) { name = netlist.Path.DefinitionPath.Grow(name); } // Extract the subcircuit definition statements StatementsToken body = (StatementsToken)st.Parameters[st.Parameters.Count - 1]; SubcircuitDefinition definition = new SubcircuitDefinition(name, body); // Parse nodes and parameters bool mode = true; // true = nodes, false = parameters for (int i = 1; i < st.Parameters.Count - 1; i++) { if (mode) { // After this, only parameters will follow if (st.Parameters[i].image.ToLower() == "params:") { mode = false; } // Parameters have started, so we will keep reading parameters else if (st.Parameters[i].kind == ASSIGNMENT) { mode = false; AssignmentToken at = st.Parameters[i] as AssignmentToken; definition.Defaults.Add(new CircuitIdentifier(at.Name.image), at.Value); } // Still reading nodes else if (ReaderExtension.IsNode(st.Parameters[i])) { definition.Pins.Add(new CircuitIdentifier(st.Parameters[i].image)); } } else if (st.Parameters[i].kind == ASSIGNMENT) { AssignmentToken at = st.Parameters[i] as AssignmentToken; definition.Defaults.Add(new CircuitIdentifier(at.Name.image), at.Value); } } // Create a new subcircuit path SubcircuitPath orig = netlist.Path; netlist.Path = new SubcircuitPath(orig, definition); foreach (var s in definition.Body.Statements(StatementType.Subcircuit)) { netlist.Readers.Read(s, netlist); } // Restore netlist.Path = orig; // Return values netlist.Definitions.Add(definition.Name, definition); Generated = definition; return(true); }
/// <summary> /// Read a transistor model /// </summary> /// <param name="type">Type</param> /// <param name="st">Statement</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { // Errors switch (st.Parameters.Count) { case 0: throw new ParseException(st.Name, "Model name and type expected", false); } // The model depends on the model level, find the model statement int level = 0; string version = null; int lindex = -1, vindex = -1; for (int i = 0; i < st.Parameters.Count; i++) { if (st.Parameters[i].kind == ASSIGNMENT) { AssignmentToken at = st.Parameters[i] as AssignmentToken; if (at.Name.image.ToLower() == "level") { lindex = i; level = (int)Math.Round(netlist.ParseDouble(at.Value)); } if (at.Name.image.ToLower() == "version") { vindex = i; version = at.Value.image.ToLower(); } if (vindex >= 0 && lindex >= 0) { break; } } } if (lindex >= 0) { st.Parameters.RemoveAt(lindex); } if (vindex >= 0) { st.Parameters.RemoveAt(vindex < lindex ? vindex : vindex - 1); } // Generate the model ICircuitObject model = null; if (Levels.ContainsKey(level)) { model = Levels[level].Invoke(new CircuitIdentifier(st.Name.image), type, version); } else { throw new ParseException(st.Name, $"Unknown mosfet model level {level}"); } // Read all the parameters netlist.ReadParameters((IParameterized)model, st.Parameters); // Output netlist.Circuit.Objects.Add(model); Generated = model; return(true); }
/// <summary> /// Read /// </summary> /// <param name="type">Type</param> /// <param name="st">Statement</param> /// <param name="netlist">Netlist</param> /// <returns></returns> public override bool Read(string type, Statement st, Netlist netlist) { // Initialize List <CircuitIdentifier> instancepins = new List <CircuitIdentifier>(); Dictionary <CircuitIdentifier, Token> instanceparameters = new Dictionary <CircuitIdentifier, Token>(); CircuitIdentifier definition = null; // Get the name CircuitIdentifier name; if (netlist.Path.InstancePath != null) { name = netlist.Path.InstancePath.Grow(st.Name.image); } else { name = new CircuitIdentifier(st.Name.image); } // Format: <NAME> <NODES>* <SUBCKT> <PAR1>=<VAL1> ... // Or: <NAME> <NODES>* <SUBCKT> params: <PAR1>=<VAL1> ... bool mode = true; // true = nodes, false = parameters for (int i = 0; i < st.Parameters.Count; i++) { // Reading nodes if (mode) { if (ReaderExtension.IsNode(st.Parameters[i])) { instancepins.Add(definition = new CircuitIdentifier(st.Parameters[i].image)); } else { instancepins.RemoveAt(instancepins.Count - 1); mode = false; } } // Reading parameters // Don't use ELSE! We still need to read the last parameter if (!mode) { if (st.Parameters[i].kind == ASSIGNMENT) { AssignmentToken at = st.Parameters[i] as AssignmentToken; switch (at.Name.kind) { case WORD: case IDENTIFIER: instanceparameters.Add(new CircuitIdentifier(at.Name.image), at.Value); break; default: throw new ParseException(at.Name, "Parameter name expected"); } } } } // If there are only node-like tokens, then the last one is the definition by default if (mode) { instancepins.RemoveAt(instancepins.Count - 1); } // Modify the instancepins to be local or use the nodemap for (int i = 0; i < instancepins.Count; i++) { if (netlist.Path.NodeMap.TryGetValue(instancepins[i], out CircuitIdentifier node)) { instancepins[i] = node; } else if (netlist.Path.InstancePath != null) { instancepins[i] = netlist.Path.InstancePath.Grow(instancepins[i].Name); } } // Find the subcircuit definition if (netlist.Path.DefinitionPath != null) { definition = netlist.Path.DefinitionPath.Grow(definition); } SubcircuitDefinition subcktdef = netlist.Path.FindDefinition(netlist.Definitions, definition) ?? throw new ParseException(st.Parameters[st.Parameters.Count - 1], "Cannot find subcircuit definition"); Subcircuit subckt = new Subcircuit(subcktdef, name, instancepins, instanceparameters); SubcircuitPath orig = netlist.Path; netlist.Path = new SubcircuitPath(netlist, orig, subckt); // Read all control statements foreach (var s in subcktdef.Body.Statements(StatementType.Control)) { netlist.Readers.Read(s, netlist); } // Read all model statements foreach (var s in subcktdef.Body.Statements(StatementType.Model)) { netlist.Readers.Read(s, netlist); } // Read all component statements foreach (var s in subcktdef.Body.Statements(StatementType.Component)) { netlist.Readers.Read(s, netlist); } // Restore netlist.Path = orig; Generated = subckt; return(true); }