gusucode.com > symbolic工具箱matlab源码程序 > symbolic/symWriteSSC.m
function symWriteSSC(newComponentName, templateComponentName, equations, varargin) %symWriteSSC Creates a new Simscape component % symWriteSSC(newComponentName, templateComponentName, equations) % creates a new Simscape component newComponentName using an existing template component % templateComponentName. % The new component is created by using all the decorations from the template component. % The given equations are added to the new component. % % symWriteSSC(newComponentName, templateComponentName, equations, NAME1, VALUE1,...) uses % the specified name-value pairs for customizing the newly created component. % The names can be any of the following: % % 'H1Header': The value must be a string given as a row vector of chars. If the string does % not start with a '%' character the '%' character is prepended. % % 'HelpText': The value must be a cell array of strings given as a row vector of chars. If a % string does not start with a '%' character the '% ' character is prepended. % % So the new component is a copy of the template component with the new H1 header line % and the new help text if specified. Additionally the given equations are added % to the new component. % % See also symReadSSCParameters, symReadSSCVariables % Copyright 2015 The MathWorks, Inc. narginchk(3,7); % check the parameters % First the name-value pairs args = varargin(1:end); opts = getOptions(args); % first the type checks validateattributes(templateComponentName, {'char'}, {'row'}); validateattributes(newComponentName, {'char'}, {'row'}); % If H1Header is not a valid h1 header line add the missing '% ' if ~isempty(regexp(opts.H1Header,'^\s*(%{|%%)','ONCE')) || ~isempty(regexp(opts.H1Header,'^\s*[^%]','ONCE')) opts.H1Header = ['%' opts.H1Header]; end % Add '% ' to the help text if it is not a valid help line for i=1:length(opts.HelpText) if ~isempty(regexp(opts.HelpText{i},'^\s*(%{|%%)','ONCE')) || ~isempty(regexp(opts.HelpText{i},'^\s*[^%]','ONCE')) || isempty(opts.HelpText{i}) opts.HelpText{i} = ['% ' opts.HelpText{i}]; end end % Check if the template component exist try templatePath = simscape.smt.internal.get_full_path(templateComponentName); catch ME if isequal(ME.identifier,'MATLAB:undefinedVarOrClass') error(message('symbolic:symSSC:SimscapeRequired')); else rethrow(ME); end end [~,templateComponentName,~] = fileparts(templatePath); % If the .ssc suffix is missing append it to the new component name [~,componentName,ext] = fileparts(newComponentName); componentFileName = newComponentName; if isempty(ext) componentFileName = [componentFileName, '.ssc']; else if ~strcmp(ext, '.ssc') error(message('symbolic:symSSC:InvalidComponentName', newComponentName)); end end componentFileName = pathToFullPath(componentFileName); if strcmp(pathToFullPath(templatePath), componentFileName) error(message('symbolic:symSSC:DifferentComponentNamesNeeded', componentName, templateComponentName)); end % equations must be a vector of symbolic equations validateattributes(equations, {'sym'}, {'vector'}); retValue = boolean(feval(symengine,'symobj::isListOfEquations', equations)); if retValue == 0 error(message('symbolic:symSSC:VectorOfEquationsExpected')); end % Do some plausibilty checks about the variables and parameters used inside the equations. % This will also check if the template component is valid try [varNames, ~, ~] = symReadSSCVariables(templateComponentName); [parNames, ~, ~] = symReadSSCParameters(templateComponentName); catch ME if isequal(ME.identifier,'symbolic:symSSC:DomainsNotSupported') error(message('symbolic:symSSC:DomainsNotSupported')); else rethrow(ME); end end vEquations = symvar(equations); % In every case 't' is allowed in the equations vEquations = setdiff(vEquations, sym('t')); notDeclared = setdiff(vEquations,union([varNames{:}],[parNames{:}])); if ~isempty(notDeclared) for i=1:length(notDeclared) warning(message('symbolic:symSSC:UndeclaredVariablesInEquation', char(notDeclared(i)))); end end % Read the template component and put it in a cell array line by line templateString = fileread(templatePath); newLine = char(10); linesOfTemplateString = textscan(templateString, '%s', 'WhiteSpace', '', 'Delimiter', newLine); linesOfTemplateString = linesOfTemplateString{1}; componentLine = findComponentLine(linesOfTemplateString); if componentLine == 0 error(message('symbolic:symSSC:DomainsNotSupported')); end endOfComponent = findEndComponentLine(linesOfTemplateString, componentLine+1); newComponentLine = getNewComponentLine(linesOfTemplateString, componentLine, componentName); h1HeaderLine = findH1HeaderLine(linesOfTemplateString, componentLine+1); if h1HeaderLine == 0 helpStart = 0; helpEnd = 0; else [helpStart, helpEnd] = findHelpText(linesOfTemplateString, h1HeaderLine+1); end [equationsStart, equationsEnd] = findEquations(linesOfTemplateString, componentLine+1, endOfComponent-1); % Write the component writeNewComponent(linesOfTemplateString, componentFileName, newComponentLine, opts.H1Header, opts.HelpText, equations, ... componentLine, h1HeaderLine, helpStart, helpEnd, equationsStart, equationsEnd, endOfComponent) end % helper functions function line = skipBlockComments(linesOfTemplateString, startLine) numberOfCommentBlocks = 0; for i=startLine:length(linesOfTemplateString) found = regexp(linesOfTemplateString{i}, '^\s*%{\s*', 'once', 'start'); if ~isempty(found) numberOfCommentBlocks = numberOfCommentBlocks+1; continue; end if numberOfCommentBlocks > 0 found = regexp(linesOfTemplateString{i}, '^\s*%}\s*', 'once', 'start'); if ~isempty(found) numberOfCommentBlocks = numberOfCommentBlocks-1; end else line = i; break; end end if i == length(linesOfTemplateString) && numberOfCommentBlocks == 0 && ~isempty(found) line = 0; end end function componentLine = findComponentLine(linesOfTemplateString) componentLine = 0; k = 1 ; while k <= length(linesOfTemplateString) k = skipBlockComments(linesOfTemplateString, k); found = regexp(linesOfTemplateString{k}, '^\s*component[\s\(]', 'once', 'start'); if ~isempty(found) componentLine=k; break; else k = k+1; end end end function endLine = findEndComponentLine(linesOfTemplateString, startLine) endLine = 0; k = startLine; while k <= length(linesOfTemplateString) k = skipBlockComments(linesOfTemplateString, k); if k == 0 break; end found = regexp(linesOfTemplateString{k}, '^\s*end', 'once', 'start'); if ~isempty(found) endLine=k; end k = k+1; end end function newLine = getNewComponentLine(linesOfTemplateString, componentLine, componentName) pattern = '(?<start>\s*component(\s+)?)(?<name>\s[^\(\s%<]+|\(.*\)\s*[^%<\s]+)(?<rest>(.*)?)'; res = regexp(linesOfTemplateString{componentLine}, pattern, 'names'); startIndexName = regexp(res.name,'\S+$'); newLine = [res.start res.name(1:startIndexName-1) componentName res.rest]; end function h1HeaderLine = findH1HeaderLine(linesOfTemplateString, startLine) h1HeaderLine = 0; if startLine <= length(linesOfTemplateString) found = regexp(linesOfTemplateString{startLine}, '^\s*%([^%{])', 'once', 'start'); if ~isempty(found) h1HeaderLine=startLine; end end end function [helpStart, helpEnd] = findHelpText(linesOfTemplateString, startLine) helpStart= 0; helpEnd = 0; for i=startLine:length(linesOfTemplateString) % Search for the correct comment lines found = regexp(linesOfTemplateString{i}, '^\s*%([^%{])', 'once', 'start'); if isempty(found) break; else if helpStart == 0 helpStart = i; end helpEnd = i; end end end function [equationsStart, equationsEnd] = findEquations(linesOfTemplateString, startLine, endLine) equationsStart = 0; equationsEnd = 0; k = startLine ; % Get the start line while k <= length(linesOfTemplateString) k = skipBlockComments(linesOfTemplateString, k); if k == 0 break; end found = regexp(linesOfTemplateString{k}, '^\s*equations', 'once', 'start'); if ~isempty(found) equationsStart=k; break; else k = k+1; end end if equationsStart ~= 0 % Get the end line while k <= endLine k = skipBlockComments(linesOfTemplateString, k); found = regexp(linesOfTemplateString{k}, '^\s*end', 'once', 'start'); if ~isempty(found) equationsEnd=k; end k = k+1; end end end % Write the new component to a file function writeNewComponent(linesOfTemplateString, componentFileName, newComponentLine, h1Header, helpText, equations, ... componentLine, h1HeaderLine, helpStart, helpEnd, equationsStart, equationsEnd, endOfComponent) [fid, message] = fopen(componentFileName, 'wt'); if fid == -1 error(message); end try for i=1:componentLine-1 fprintf(fid, '%s\n', linesOfTemplateString{i}); end fprintf(fid, '%s\n', newComponentLine); if isempty(h1Header) if h1HeaderLine ~= 0 % Write the existing one fprintf(fid, '%s\n', linesOfTemplateString{h1HeaderLine}); end else % Write the new H1 header fprintf(fid, '%s\n', h1Header); end if isempty(helpText) if helpStart ~= 0 % Write the exiting help text for i=helpStart:helpEnd fprintf(fid, '%s\n', linesOfTemplateString{i}); end end else % Write the new help text for i=1:length(helpText) fprintf(fid, '%s\n', helpText{i}); end end % Skip the help part from the template if helpStart == 0 if h1HeaderLine ~= 0 helpEnd = h1HeaderLine; else helpEnd = componentLine; end end if equationsStart == 0 for i=helpEnd+1:endOfComponent-1 fprintf(fid, '%s\n', linesOfTemplateString{i}); end fprintf(fid, ' equations\n'); else for i=helpEnd+1:equationsEnd-1 fprintf(fid, '%s\n', linesOfTemplateString{i}); end end % Insert the new equations before the end for elem = equations childs = children(elem); simElem = simscapeEquation(childs(1), childs(2)); fprintf(fid, '%s\n', [' ' simElem]); end if equationsStart == 0 fprintf(fid, ' end\n'); % Write the rest of the file for i=endOfComponent:length(linesOfTemplateString) fprintf(fid, '%s\n', linesOfTemplateString{i}); end else % Write the rest of the file for i=equationsEnd:length(linesOfTemplateString) fprintf(fid, '%s\n', linesOfTemplateString{i}); end end fclose(fid); catch ME fclose(fid); rethrow(ME); end end % parse inputs and return options structure output using the input parser function opts = getOptions(args) ip = inputParser; ip.addParameter('H1Header','',@isValidH1Header); ip.addParameter('HelpText',{},@isValidHelptext); ip.parse(args{:}); opts = ip.Results; % 'H1Header' was set explicitly by the user if isempty(find(strcmp(ip.UsingDefaults, 'H1Header'),1)) if isempty(opts.H1Header) opts.H1Header = '%'; end end % 'HelpText' was set explicitly by the user if isempty(find(strcmp(ip.UsingDefaults, 'HelpText'),1)) if isempty(opts.HelpText) opts.HelpText = {'%'}; end end end function result = isValidH1Header(h1Header) % empty string is allowed if ~(ischar(h1Header) && isempty(h1Header)) validateattributes(h1Header, {'char'}, {'row'}); end result = true; end function result = isValidHelptext(helpText) % help text should be a cell array of strings validateattributes(helpText, {'cell'}, {}); if ~isempty(helpText) validateattributes(helpText, {'cell'}, {'vector'}); for i=1:length(helpText) % empty strings are allowed if ~(ischar(helpText{i}) && isempty(helpText{i})) validateattributes(helpText{i}, {'char'}, {'row'}); end end end result = true; end function fullPath = pathToFullPath(file) validateattributes(file, {'char'}, {'row'}); if java.io.File.isAbsolute(java.io.File(file)) fullPath = file; else fullPath = fullfile(pwd,file) ; end fullPath = char(java.io.File.getCanonicalPath(java.io.File(fullPath))); end