This package contains quite involved examples that demonstrate how to use the functions of package Modelica.Utilities. In particular the following examples are present.
Name | Description |
---|---|
calculator | Interpreter to evaluate simple expressions consisting of +,-,*,/,(),sin(), cos(), tan(), sqrt(), pi |
expression | Expression interpreter that returns with the position after the expression (expression may consist of +,-,*,/,(),sin(), cos(), tan(), sqrt(), pi |
readRealParameter | Read the value of a Real parameter from file |
readRealParameterModel | Demonstrate usage of Examples.readRealParameter/.expression |
result = calculator(expression);
This function demonstrates how a simple expression calculator can be implemented in form of a recursive decent parser using basically the Strings.scanToken(..) and Strings.scanDelimiter(..) function.
The following operations are supported (pi=3.14.. is a predefined constant):
+, - *, / (expression) sin(expression) cos(expression) tan(expression) sqrt(expression) pi
calculator("2+3*(4-1)"); // returns 11 calculator("sin(pi/6)"); // returns 0.5
Extends from Modelica.Icons.Function (Icon for a function).
Type | Name | Default | Description |
---|---|---|---|
String | string | Expression that is evaluated |
Type | Name | Description |
---|---|---|
Real | result | Value of expression |
function calculator "Interpreter to evaluate simple expressions consisting of +,-,*,/,(),sin(), cos(), tan(), sqrt(), pi" import Modelica.Utilities.Strings.*; extends Modelica.Icons.Function; input String string "Expression that is evaluated"; output Real result "Value of expression"; protected Integer nextIndex; algorithm (result,nextIndex) := expression(string, 1); Strings.scanNoToken(string,nextIndex);end calculator;
result = expression(string); (result, nextIndex) = expression(string, startIndex=1, message="");
This function is nearly the same as Examples.calculator. The essential difference is that function "expression" might be used in other parsing operations: After the expression is parsed and evaluated, the function returns with the value of the expression as well as the position of the character directly after the expression.
This function demonstrates how a simple expression calculator can be implemented in form of a recursive decent parser using basically the Strings.scanToken(..) and scanDelimiters(..) function. There are 2 local functions (term, primary) that implement the corresponding part of the grammar.
The following operations are supported (pi=3.14.. is a predefined constant):
+, - *, / (expression) sin(expression) cos(expression) tan(expression) sqrt(expression) pi
The optional argument "startIndex" defines at which position scanning of the expression starts.
In case of error, the optional argument "message" is appended to the error message, in order to give additional information where the error occured.
This function parses the following grammaer
expression: [ add_op ] term { add_op term } add_op : "+" | "-" term : primary { mul_op primary } mul_op : "*" | "/" primary : UNSIGNED_NUMBER | pi | ( expression ) | functionName( expression ) function : sin | cos | tan | sqrt
Note, in Examples.readRealParameter it is shown, how the expression function can be used as part of another scan operation.
expression("2+3*(4-1)"); // returns 11 expression("sin(pi/6)"); // returns 0.5
Extends from Modelica.Icons.Function (Icon for a function).
Type | Name | Default | Description |
---|---|---|---|
String | string | Expression that is evaluated | |
Integer | startIndex | 1 | Start scanning of expression at character startIndex |
String | message | "" | Message used in error message if scan is not successful |
Type | Name | Description |
---|---|---|
Real | result | Value of expression |
Integer | nextIndex | Index after the scanned expression |
function expression "Expression interpreter that returns with the position after the expression (expression may consist of +,-,*,/,(),sin(), cos(), tan(), sqrt(), pi" import Modelica.Utilities.Types; import Modelica.Utilities.Strings; import Modelica.Math; import Modelica.Constants; extends Modelica.Icons.Function; input String string "Expression that is evaluated"; input Integer startIndex=1 "Start scanning of expression at character startIndex"; input String message="" "Message used in error message if scan is not successful"; output Real result "Value of expression"; output Integer nextIndex "Index after the scanned expression"; protectedfunction term "Evaluate term of an expression" extends Modelica.Icons.Function; input String string; input Integer startIndex; input String message=""; output Real result; output Integer nextIndex; protected Real result2; Boolean scanning=true; String opString; algorithm // scan for "primary * primary" or "primary / primary" (result, nextIndex) := primary(string, startIndex, message); while scanning loop (opString, nextIndex) := Strings.scanDelimiter( string, nextIndex, {"*","/",""}, message); if opString == "" then scanning := false; else (result2, nextIndex) := primary(string, nextIndex, message); result := if opString == "*" then result*result2 else result/result2; end if; end while; end term ;function primary "Evaluate primary of an expression" extends Modelica.Icons.Function; input String string; input Integer startIndex; input String message=""; output Real result; output Integer nextIndex; protected Types.TokenValue token; Real result2; String delimiter; String functionName; Real pi = Constants.pi; algorithm (token,nextIndex) := Strings.scanToken(string, startIndex,unsigned=true); if token.tokenType == Types.TokenType.DelimiterToken and token.string == "(" then (result,nextIndex) := expression(string, nextIndex,message); (delimiter,nextIndex) := Strings.scanDelimiter(string,nextIndex,{")"}, message); elseif token.tokenType == Types.TokenType.RealToken then result := token.real; elseif token.tokenType == Types.TokenType.IntegerToken then result := token.integer; elseif token.tokenType == Types.TokenType.IdentifierToken then if token.string == "pi" then result := pi; else functionName := token.string; (delimiter,nextIndex) := Strings.scanDelimiter(string,nextIndex,{"("}, message); (result,nextIndex) := expression(string, nextIndex, message); (delimiter,nextIndex) := Strings.scanDelimiter(string,nextIndex,{")"}, message); if functionName == "sin" then result := Math.sin(result); elseif functionName == "cos" then result := Math.cos(result); elseif functionName == "tan" then result := Math.tan(result); elseif functionName == "sqrt" then if result < 0.0 then Strings.syntaxError(string, startIndex, "Argument of call \"sqrt(" + String(result) + ")\" is negative.\n" + "Imaginary numbers are not supported by the calculator.\n" + message); end if; result := sqrt(result); else Strings.syntaxError(string, startIndex, "Function \"" + functionName + "\" is unknown (not supported)\n" + message); end if; end if; else Strings.syntaxError(string, startIndex, "Invalid primary of expression.\n" + message); end if; end primary ; Real result2; String signOfNumber; Boolean scanning=true; String opString; algorithm // scan for optional leading "+" or "-" sign (signOfNumber, nextIndex) :=Strings.scanDelimiter( string, startIndex, {"+","-",""}, message); // scan for "term + term" or "term - term" (result, nextIndex) := term(string, nextIndex, message); if signOfNumber == "-" then result := -result; end if; while scanning loop (opString, nextIndex) := Strings.scanDelimiter( string, nextIndex, {"+","-",""}, message); if opString == "" then scanning := false; else (result2, nextIndex) := term(string, nextIndex, message); result := if opString == "+" then result+result2 else result-result2; end if; end while;end expression;
result = readRealParameter(fileName, name);
This function demonstrates how a function can be implemented that reads the value of a parameter from file. The function performs the following actions:
On file "test.txt" the following lines might be present:
// Motor data J = 2.3 // inertia w_rel0 = 1.5*2; // relative angular velocity phi_rel0 = pi/3
The function returns the value "3.0" when called as:
readRealParameter("test.txt", "w_rel0")
Extends from Modelica.Icons.Function (Icon for a function).
Type | Name | Default | Description |
---|---|---|---|
String | fileName | Name of file | |
String | name | Name of parameter |
Type | Name | Description |
---|---|---|
Real | result | Actual value of parameter on file |
function readRealParameter "Read the value of a Real parameter from file" import Modelica.Utilities.*; extends Modelica.Icons.Function; input String fileName "Name of file"; input String name "Name of parameter"; output Real result "Actual value of parameter on file"; protected String line; String identifier; String delimiter; Integer nextIndex; Integer iline=1; Types.TokenValue token; String message = "in file \"" + fileName + "\" on line "; String message2; Boolean found = false; Boolean endOfFile=false; algorithm (line, endOfFile) :=Streams.readLine(fileName, iline); while not found and not endOfFile loop (token, nextIndex) := Strings.scanToken(line); if token.tokenType == Types.TokenType.NoToken then // skip line iline := iline + 1; elseif token.tokenType == Types.TokenType.IdentifierToken then if token.string == name then // name found, get value of "name = value;" message2 := message + String(iline); (delimiter,nextIndex) := Strings.scanDelimiter(line, nextIndex, {"="}, message2); (result,nextIndex) := Examples.expression(line, nextIndex, message2); (delimiter,nextIndex) := Strings.scanDelimiter(line, nextIndex, {";", ""}, message2); Strings.scanNoToken(line, nextIndex, message2); found := true; else // wrong name, skip line iline := iline + 1; end if; else // wrong token Strings.syntaxError(line, nextIndex, "Expected identifier " + message + String(iline)); end if; // read next line (line, endOfFile) :=Streams.readLine(fileName, iline); end while; if not found then Streams.error("Parameter \"" + name + "\" not found in file \"" + fileName + "\""); end if;end readRealParameter;
Model that shows the usage of Examples.readRealParameter and Examples.expression. The model has 3 parameters and the values of these parameters are read from a file.
Extends from Modelica.Icons.Example (Icon for an example model).
Type | Name | Default | Description |
---|---|---|---|
String | file | "Modelica/Utilities/data/Exa... | File on which data is present |
Inertia | J | readRealParameter(file, "J") | Inertia [kg.m2] |
Angle | phi_rel0 | readRealParameter(file, "phi... | Relative angle [rad] |
AngularVelocity | w_rel0 | readRealParameter(file, "w_r... | Relative angular velocity [rad/s] |
model readRealParameterModel "Demonstrate usage of Examples.readRealParameter/.expression" import SI = Modelica.SIunits; extends Modelica.Icons.Example; parameter String file = "Modelica/Utilities/data/Examples_readRealParameters.txt" "File on which data is present"; parameter SI.Inertia J = readRealParameter(file, "J") "Inertia"; parameter SI.Angle phi_rel0 = readRealParameter(file, "phi_rel0") "Relative angle"; parameter SI.AngularVelocity w_rel0 = readRealParameter(file, "w_rel0") "Relative angular velocity";end readRealParameterModel;