Skip to content

Commit

Permalink
Fixing Lexer to accept valid quoted identifiers
Browse files Browse the repository at this point in the history
  - Allow empty quoted ident: ''
  - Allow quoted ident with double quots: '"'
  - Sanitize quoted identifiers to fix compilation and linearization
  • Loading branch information
AnHeuermann committed Apr 17, 2024
1 parent e91ce54 commit 37a4f23
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 20 deletions.
19 changes: 16 additions & 3 deletions OMCompiler/Compiler/Template/CodegenUtil.tpl
Expand Up @@ -104,11 +104,17 @@ template crefStr(ComponentRef cr)
end crefStr;

template crefStrNoUnderscore(ComponentRef cr)
"Generates the name of a variable for variable name array. However does not use underscores on qualified names.
a.b not a._b. Used for generating variable names that are exported e.g. xml files"
"Generates the name of a variable for variable name array.
However does not use underscores on qualified names.
a.b not a._b.
Escaping single and double quotes from quoted identifiers.

Used for generating variable names that are exported e.g. xml files"
::=
match cr
case CREF_IDENT(__) then '<%ident%><%subscriptsStr(subscriptLst)%>'
case CREF_IDENT(__) then
let escapedIdent = Util.escapeModelicaStringToCString(escapeSingleQuoteIdent(ident))
'<%escapedIdent%><%subscriptsStr(subscriptLst)%>'
case CREF_QUAL(ident = "$DER") then 'der(<%crefStrNoUnderscore(componentRef)%>)'
case CREF_QUAL(ident = "$CLKPRE") then 'previous(<%crefStrNoUnderscore(componentRef)%>)'
case CREF_QUAL(__) then '<%ident%><%subscriptsStr(subscriptLst)%>.<%crefStrNoUnderscore(componentRef)%>'
Expand Down Expand Up @@ -194,6 +200,13 @@ end crefCCommentWithVariability;

/*********************************************************/

template escapeSingleQuoteIdent(String ident)
"Escape single quotes from quoted identifiers."
::=
// TODO: How to replace "'" with "\'" but not "\'" with "\\'"?
'<%System.stringReplace(System.stringReplace(ident, "\\'", "\\\\'"), "'", "\\'")%>'
end escapeSingleQuoteIdent;

template initDefaultValXml(DAE.Type type_)
::=
match type_
Expand Down
16 changes: 8 additions & 8 deletions OMCompiler/Compiler/Template/CodegenUtilSimulation.tpl
Expand Up @@ -141,21 +141,21 @@ template dumpEqsWork(list<SimEqSystem> eqs)
<<
equation index: <%equationIndex(eq)%>
type: SIMPLE_ASSIGN
<%dumpCref(e.cref)%> = <%escapeCComments(dumpExp(e.exp,"\""))%>
<%escapeCComments(dumpCref(e.cref))%> = <%escapeCComments(dumpExp(e.exp,"\""))%>
>>
case e as SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
<<
equation index: <%equationIndex(eq)%>
type: SIMPLE_ASSIGN_CONSTRAINTS
<%dumpCref(e.cref)%> = <%escapeCComments(dumpExp(e.exp,"\""))%>
<%escapeCComments(dumpCref(e.cref))%> = <%escapeCComments(dumpExp(e.exp,"\""))%>
constraints: <%escapeCComments(dumpConstraints(e.cons))%>
>>
case e as SES_ARRAY_CALL_ASSIGN(lhs=lhs as CREF(__)) then
<<
equation index: <%equationIndex(eq)%>
type: ARRAY_CALL_ASSIGN

<%dumpCref(lhs.componentRef)%> = <%escapeCComments(dumpExp(e.exp,"\""))%>
<%escapeCComments(dumpCref(lhs.componentRef))%> = <%escapeCComments(dumpExp(e.exp,"\""))%>
>>
case e as SES_GENERIC_ASSIGN(__) then
<<
Expand Down Expand Up @@ -185,7 +185,7 @@ template dumpEqsWork(list<SimEqSystem> eqs)
equation index: <%equationIndex(eq)%>
type: LINEAR

<%ls.vars |> SIMVAR(name=cr) => '<var><%dumpCref(cr)%></var>' ; separator = "\n" %>
<%ls.vars |> SIMVAR(name=cr) => '<var><%escapeCComments(dumpCref(cr))%></var>' ; separator = "\n" %>
<row>
<%ls.beqs |> exp => '<cell><%escapeCComments(dumpExp(exp,"\""))%></cell>' ; separator = "\n" %><%\n%>
</row>
Expand Down Expand Up @@ -218,7 +218,7 @@ template dumpEqsWork(list<SimEqSystem> eqs)
indexNonlinear: <%nls.indexNonLinearSystem%>
type: NONLINEAR

vars: {<%nls.crefs |> cr => '<%dumpCref(cr)%>' ; separator = ", "%>}
vars: {<%nls.crefs |> cr => '<%escapeCComments(dumpCref(cr))%>' ; separator = ", "%>}
eqns: {<%nls.eqs |> eq => '<%equationIndex(eq)%>' ; separator = ", "%>}
>>
case e as SES_MIXED(__) then
Expand All @@ -231,7 +231,7 @@ template dumpEqsWork(list<SimEqSystem> eqs)

<mixed>
<continuous index="<%equationIndex(e.cont)%>" />
<%e.discVars |> SIMVAR(name=cr) => '<var><%dumpCref(cr)%></var>' ; separator = ","%>
<%e.discVars |> SIMVAR(name=cr) => '<var><%escapeCComments(dumpCref(cr))%></var>' ; separator = ","%>
<%e.discEqs |> eq => '<discrete index="<%equationIndex(eq)%>" />'%>
</mixed>
>>
Expand All @@ -251,7 +251,7 @@ template dumpEqsWork(list<SimEqSystem> eqs)
equation index: <%equationIndex(eq)%>
type: WHEN

when {<%conditions |> cond => '<%dumpCref(cond)%>' ; separator=", " %>} then
when {<%conditions |> cond => '<%escapeCComments(dumpCref(cond))%>' ; separator=", " %>} then
<%body%>
end when;
>>
Expand All @@ -269,7 +269,7 @@ template dumpEqsWork(list<SimEqSystem> eqs)
let &forstatement = buffer ""
let &forstatement += 'for ' + escapeCComments(dumpExp(e.iter,"\"")) + ' in ' + escapeCComments(dumpExp(e.startIt,"\""))
let &forstatement += ' : ' + escapeCComments(dumpExp(e.endIt,"\"")) + ' loop<%\n%>'
let &forstatement += ' <%dumpCref(e.cref)%> = <%escapeCComments(dumpExp(e.exp,"\""))%>; '
let &forstatement += ' <%escapeCComments(dumpCref(e.cref))%> = <%escapeCComments(dumpExp(e.exp,"\""))%>; '
let &forstatement += 'end for'
<<
equation index: <%equationIndex(e)%>
Expand Down
16 changes: 10 additions & 6 deletions testsuite/flattening/modelica/mosfiles/QuotedIdentifier.mo
Expand Up @@ -5,11 +5,15 @@ model QuotedIdentifier
Real 'h\'i //j';
Real '\\\\\'';
Real '';
Real '*/ no code injection';
Real '\'';
equation
der('a"b')=1;
der('c d')=-1;
der('e"f g')=2;
der('h\'i //j')=-2;
der('\\\\\'')=3;
der('')=-3;
der('a"b') = 1;
der('c d') = -1;
der('e"f g') = 2;
der('h\'i //j') = -2;
der('\\\\\'') = 3;
der('') = -3;
der('*/ no code injection') = 4;
der('\'') = -4;
end QuotedIdentifier;
41 changes: 38 additions & 3 deletions testsuite/flattening/modelica/mosfiles/QuotedIdentifier.mos
@@ -1,15 +1,50 @@
// name: QuotedIdentifier
// status: correct
// teardown_command: rm -rf QuotedIdentifier_tmp
//
// Test compilation of C code containing */ or ".
// Test lineariazion of modle with quoted identifiers containing additional '.

loadFile("QuotedIdentifier.mo");getErrorString();

echo(false);
mkdir("QuotedIdentifier_tmp"); cd("QuotedIdentifier_tmp");
echo(true);

translate(QuotedIdentifier); getErrorString();
simulate(QuotedIdentifier); getErrorString();
buildModel(QuotedIdentifier); getErrorString();
linearize(QuotedIdentifier); getErrorString();

// Result:
loadFile("linearized_model.mo"); getErrorString();

simulate(linearized_model); getErrorString();

// Result:
// true
// ""
// true
// {"QuotedIdentifier","QuotedIdentifier_init.xml"}
// "Warning: The initial conditions are not fully specified. For more information set -d=initialization. In OMEdit Tools->Options->Simulation->Show additional information from the initialization process, in OMNotebook call setCommandLineOptions(\"-d=initialization\").
// "
// record SimulationResult
// resultFile = "QuotedIdentifier_res.mat",
// simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 1e-6, method = 'dassl', fileNamePrefix = 'QuotedIdentifier', options = '', outputFormat = 'mat', variableFilter = '.*', cflags = '', simflags = ''",
// messages = "LOG_STDOUT | info | Linearization will be performed at point of time: 1.000000
// LOG_SUCCESS | info | The initialization finished successfully without homotopy method.
// LOG_SUCCESS | info | The simulation finished successfully.
// LOG_STDOUT | info | Linear model is created.
// "
// end SimulationResult;
// "Warning: The initial conditions are not fully specified. For more information set -d=initialization. In OMEdit Tools->Options->Simulation->Show additional information from the initialization process, in OMNotebook call setCommandLineOptions(\"-d=initialization\").
// "
// true
// ""
// record SimulationResult
// resultFile = "linearized_model_res.mat",
// simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 1e-6, method = 'dassl', fileNamePrefix = 'linearized_model', options = '', outputFormat = 'mat', variableFilter = '.*', cflags = '', simflags = ''",
// messages = "LOG_SUCCESS | info | The initialization finished successfully without homotopy method.
// LOG_SUCCESS | info | The simulation finished successfully.
// "
// end SimulationResult;
// "Warning: The initial conditions are not fully specified. For more information set -d=initialization. In OMEdit Tools->Options->Simulation->Show additional information from the initialization process, in OMNotebook call setCommandLineOptions(\"-d=initialization\").
// "
// endResult

0 comments on commit 37a4f23

Please sign in to comment.