private Node ParseTerminal(ILexer lexer) { Node result; switch (lexer.Token) { // Nested case TokenType.LeftParenthesis: lexer.ReadToken(); result = ParseConditional(lexer); if (lexer.Token != TokenType.RightParenthesis) { throw new Exception("Unclosed parenthesis"); } lexer.ReadToken(); break; // A number case TokenType.Number: result = Node.Constant(SpiceHelper.ParseNumber(lexer.Content)); lexer.ReadToken(); break; // Can be a variable or a function call case TokenType.Identifier: string name = lexer.Content; lexer.ReadToken(); if (lexer.Token == TokenType.LeftParenthesis) { // Function call! string function = null; switch (name.ToLowerInvariant()) { case "vr": function = "real"; goto case "v"; case "vi": function = "imag"; goto case "v"; case "vm": function = "abs"; goto case "v"; case "vdb": function = "db"; goto case "v"; case "vph": function = "phase"; goto case "v"; case "v": // Read the nodes lexer.ReadNode(); result = Node.Voltage(lexer.Content); lexer.ReadToken(); if (lexer.Token == TokenType.Comma) { lexer.ReadNode(); result = Node.Subtract(result, Node.Voltage(lexer.Content)); lexer.ReadToken(); } if (lexer.Token != TokenType.RightParenthesis) { throw new Exception("Invalid voltage specifier"); } lexer.ReadToken(); break; case "ir": function = "real"; goto case "i"; case "ii": function = "imag"; goto case "i"; case "im": function = "abs"; goto case "i"; case "idb": function = "db"; goto case "i"; case "iph": function = "phase"; goto case "i"; case "i": // Read the name lexer.ReadNode(); result = Node.Current(lexer.Content); lexer.ReadToken(); if (lexer.Token != TokenType.RightParenthesis) { throw new Exception("Invalid current specifier"); } lexer.ReadToken(); break; default: var arguments = new List <Node>(2); // Let's go to the first token after the function call lexer.ReadToken(); while (lexer.Token != TokenType.RightParenthesis) { // Read the argument arguments.Add(ParseConditional(lexer)); // Continue with another argument if (lexer.Token == TokenType.Comma) { lexer.ReadToken(); } else if (lexer.Token != TokenType.RightParenthesis) { throw new Exception("Invalid function call"); } } result = Node.Function(name, arguments); lexer.ReadToken(); break; } if (function != null) { result = Node.Function(function, new[] { result }); } } else { result = Node.Variable(name); // We already read the next token, no need to do it here again... } break; case TokenType.At: lexer.ReadNode(); name = lexer.Content; lexer.ReadToken(); if (lexer.Token != TokenType.LeftIndex) { throw new Exception("Invalid property identifier"); } lexer.ReadNode(); result = Node.Property(name, lexer.Content); lexer.ReadToken(); if (lexer.Token != TokenType.RightIndex) { throw new Exception("Invalid property identifier"); } lexer.ReadToken(); break; // There is no level below this, so let's throw an exception default: throw new Exception("Invalid value"); } return(result); }
private static Node ParseTerminal(Lexer lexer) { Node result; switch (lexer.Type) { case TokenType.LeftParenthesis: lexer.Next(); result = ParseConditional(lexer); if (lexer.Type != TokenType.RightParenthesis) { throw new ParserException("Expected closing parenthesis, but found '{0}'".FormatString(lexer.Content)); } lexer.Next(); break; case TokenType.Number: result = SpiceHelper.ParseNumber(lexer.Content); lexer.Next(); break; case TokenType.Identifier: string name = lexer.Content; lexer.Next(); if (lexer.Type == TokenType.LeftParenthesis) { // Function call! lexer.Next(); string function = null; switch (name.ToLowerInvariant()) { case "vr": function = "real"; goto case "v"; case "vi": function = "imag"; goto case "v"; case "vm": function = "abs"; goto case "v"; case "vdb": function = "db"; goto case "v"; case "vp": function = "arg"; goto case "v"; case "v": // Read the nodes lexer.ContinueWhileNode(); result = Node.Voltage(lexer.Content); lexer.Next(); if (lexer.Type == TokenType.Comma) { lexer.Next(); lexer.ContinueWhileNode(); result = Node.Subtract(result, Node.Voltage(lexer.Content)); lexer.Next(); } if (lexer.Type != TokenType.RightParenthesis) { throw new ParserException(lexer, "Expected closing parenthesis but found '{0}'".FormatString(lexer.Content)); } lexer.Next(); break; case "ir": function = "real"; goto case "i"; case "ii": function = "imag"; goto case "i"; case "im": function = "abs"; goto case "i"; case "idb": function = "db"; goto case "i"; case "ip": function = "arg"; goto case "i"; case "i": // Read the nodes lexer.ContinueWhileNode(); result = Node.Current(lexer.Content); lexer.Next(); if (lexer.Type != TokenType.RightParenthesis) { throw new ParserException("Expected closing parenthesis but found '{0}'".FormatString(lexer.Content)); } lexer.Next(); break; default: var arguments = new List <Node>(2); while (lexer.Type != TokenType.RightParenthesis) { arguments.Add(ParseConditional(lexer)); // continue if (lexer.Type == TokenType.Comma) { lexer.Next(); } else if (lexer.Type != TokenType.RightParenthesis) { throw new ParserException("Expected closing parenthesis but found '{0}'".FormatString(lexer.Content)); } } result = Node.Function(name, arguments); lexer.Next(); break; } if (function != null) { Node.Function(function, new[] { result }); } } else { result = Node.Variable(name); } break; case TokenType.At: lexer.Next(); lexer.ContinueWhileNode(); name = lexer.Content; lexer.Next(); if (lexer.Type != TokenType.LeftIndex) { throw new ParserException("Expected property indexing, but found '{0}'".FormatString(lexer.Content)); } lexer.Next(); lexer.ContinueWhileNode(); result = Node.Property(name, lexer.Content); if (lexer.Type != TokenType.RightIndex) { throw new ParserException("Expected closing indexer, but found '{0}'".FormatString(lexer.Content)); } break; default: throw new ParserException("Invalid value"); } return(result); }