Skip to content

Commit

Permalink
- Added regex and regexBool scripting functions, and a testcase
Browse files Browse the repository at this point in the history
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@7860 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Feb 3, 2011
1 parent bd06224 commit b62b793
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 22 deletions.
30 changes: 28 additions & 2 deletions Compiler/FrontEnd/ModelicaBuiltin.mo
Expand Up @@ -694,13 +694,39 @@ algorithm
end readFilePostprocessLineDirective;
*/

function regex "WARNING: This call is subject to change. It should return a tuple: enum(Found,NotFound,Failure) and the (first) matching substring"
function regex "Sets the error buffer and returns -1 if the regex does not compile.
The returned result is the same as POSIX regex():
The first value is the complete matched string
The rest are the substrings that you wanted.
For example:
regex(lorem,\" \([A-Za-z]*\) \([A-Za-z]*\) \",maxMatches=3)
=> {\" ipsum dolor \",\"ipsum\",\"dolor\"}
This means if you have n groups, you want maxMatches=n+1
"
input String str;
input String re;
output Boolean status;
input Integer maxMatches := 1 "The maximum number of matches that will be returned";
input Boolean extended := true "Use POSIX extended or regular syntax";
input Boolean caseInsensitive := false;
output Integer numMatches "-1 is an error, 0 means no match, else returns a number 1..maxMatches";
output String matchedSubstrings[maxMatches] "unmatched strings are returned as empty";
external "builtin";
end regex;

function regexBool "Returns true if the string matches the regular expression"
input String str;
input String re;
input Boolean extended := true "Use POSIX extended or regular syntax";
input Boolean caseInsensitive := false;
output Boolean matches;
protected
Integer numMatches;
algorithm
numMatches := regex(str,re,0,extended,caseInsensitive);
matches := numMatches == 1;
end regexBool;

function readFileNoNumeric
"Returns the contents of the file, with anything resembling a (real) number stripped out, and at the end adding:
Filter count from number domain: n.
Expand Down
22 changes: 16 additions & 6 deletions Compiler/Script/CevalScript.mo
Expand Up @@ -649,11 +649,11 @@ algorithm
Values.Value ret_val,simValue,size_value,value,v;
DAE.Exp exp,size_expression,bool_exp,storeInTemp,translationLevel,addOriginalIncidenceMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,xRange,yRange,varName,varTimeStamp;
Absyn.ComponentRef cr_1;
Integer size,length,resI,timeStampI,i;
list<String> vars_1,vars_2,args,strings,strVars;
Integer size,length,resI,timeStampI,i,n;
list<String> vars_1,vars_2,args,strings,strVars,strs;
Real t1,t2,time,timeTotal,timeSimulation,timeStamp,val;
Interactive.InteractiveStmts istmts;
Boolean bval, b, legend, grid, logX, logY, points, gcc_res, omcfound, rm_res, touch_res, uname_res;
Boolean bval, b, legend, grid, logX, logY, points, gcc_res, omcfound, rm_res, touch_res, uname_res, extended, insensitive;
Env.Cache cache;
list<Interactive.LoadedFile> lf;
AbsynDep.Depends aDep;
Expand Down Expand Up @@ -720,11 +720,21 @@ algorithm
then
(cache,Values.BOOL(true),newst);

case (cache,env,"regex",{Values.STRING(str),Values.STRING(re)},st,msg)
case (cache,env,"regex",{Values.STRING(str),Values.STRING(re),Values.INTEGER(i),Values.BOOL(extended),Values.BOOL(insensitive)},st,msg)
equation
b = System.regex(str,re);
(n,strs) = System.regex(str,re,i,extended,insensitive);
vals = Util.listMap(strs,ValuesUtil.makeString);
v = Values.ARRAY(vals,{i});
then
(cache,Values.BOOL(b),st);
(cache,Values.TUPLE({Values.INTEGER(n),v}),st);

case (cache,env,"regex",{Values.STRING(str),Values.STRING(re),Values.INTEGER(i),Values.BOOL(extended),Values.BOOL(insensitive)},st,msg)
equation
strs = Util.listFill("",i);
vals = Util.listMap(strs,ValuesUtil.makeString);
v = Values.ARRAY(vals,{i});
then
(cache,Values.TUPLE({Values.INTEGER(-1),v}),st);

case (cache,env,"list",{},(st as Interactive.SYMBOLTABLE(ast = p)),msg)
equation
Expand Down
21 changes: 17 additions & 4 deletions Compiler/Util/System.mo
Expand Up @@ -95,12 +95,25 @@ public function stringFindString "locates substring searchStr in str. If succeed
external "C" outString=System_stringFindString(str,searchStr) annotation(Library = "omcruntime");
end stringFindString;

public function regex "Returns true if the string matches the regular expression"
public function regex "Fails and sets Error.mo if the regex does not compile.
The returned result is the same as POSIX regex():
The first value is the complete matched string
The rest are the substrings that you wanted.
For example:
regex(lorem,\" \([A-Za-z]*\) \([A-Za-z]*\) \",maxMatches=3)
=> {\" ipsum dolor \",\"ipsum\",\"dolor\"}
This means if you have n groups, you want maxMatches=n+1
"
input String str;
input String re;
output Boolean matches;
input Integer maxMatches "The maximum number of matches that will be returned";
input Boolean extended "Use POSIX extended or regular syntax";
input Boolean sensitive;
output Integer numMatches "0 means no match, else returns a number 1..maxMatches (1 if maxMatches<0)";
output list<String> strs "This list has length = maxMatches. Substrings that did not match are filled with the empty string";

external "C" matches=System_regex(str,re) annotation(Library = "omcruntime");
external "C" numMatches=System_regex(str,re,maxMatches,extended,sensitive,strs) annotation(Library = "omcruntime");
end regex;

public function strncmp
Expand Down Expand Up @@ -141,7 +154,7 @@ public function strtok
input String token;
output list<String> strings;

external "C" string=System_strtok(string,token) annotation(Library = "omcruntime");
external "C" strings=System_strtok(string,token) annotation(Library = "omcruntime");
end strtok;

public function substring
Expand Down
5 changes: 3 additions & 2 deletions Compiler/runtime/System_omc.cpp
Expand Up @@ -495,9 +495,10 @@ extern const char* System_getCorbaLibs()
return CONFIG_CORBALIBS;
}

extern int System_regex(const char *str, const char *re)
extern void* System_regex(const char* str, const char* re, int maxn, int extended, int sensitive, int *nmatch)
{
int res = SystemImpl__regex(str,re);
void *res = SystemImpl__regex(str,re,maxn,extended,sensitive,nmatch);
if (res==NULL) MMC_THROW();
return res;
}

Expand Down
8 changes: 6 additions & 2 deletions Compiler/runtime/System_rml.c
Expand Up @@ -1949,7 +1949,11 @@ RML_END_LABEL

RML_BEGIN_LABEL(System__regex)
{
rmlA0 = mk_icon(SystemImpl__regex(RML_STRINGDATA(rmlA0),RML_STRINGDATA(rmlA1)));
RML_TAILCALLK(rmlSC);
int nmatch;
rmlA1 = SystemImpl__regex(RML_STRINGDATA(rmlA0),RML_STRINGDATA(rmlA1),RML_UNTAGFIXNUM(rmlA2),RML_UNTAGFIXNUM(rmlA3),RML_UNTAGFIXNUM(rmlA4),&nmatch);
rmlA0 = mk_icon(nmatch);
if (rmlA1)
RML_TAILCALLK(rmlSC);
RML_TAILCALLK(rmlFC);
}
RML_END_LABEL
38 changes: 32 additions & 6 deletions Compiler/runtime/systemimpl.c
Expand Up @@ -967,12 +967,17 @@ extern int SystemImpl__unescapedStringLength(const char* str)
return i;
}

extern int SystemImpl__regex(const char* str, const char* re)
extern void* SystemImpl__regex(const char* str, const char* re, int maxn, int extended, int sensitive, int *nmatch)
{
void *lst;
char *dup;
regex_t myregex;
int rc,res;
regmatch_t matches[maxn];
int i,rc,res;
int flags = (extended ? REG_EXTENDED : 0) | (sensitive ? REG_ICASE : 0) | (maxn ? 0 : REG_NOSUB);
memset(&myregex, 1, sizeof(regex_t));
rc = regcomp(&myregex, re, REG_EXTENDED|REG_NOSUB);
rc = regcomp(&myregex, re, flags);
lst = mk_nil();
if (rc) {
char err_buf[2048] = {0};
int len = 0;
Expand All @@ -982,11 +987,32 @@ extern int SystemImpl__regex(const char* str, const char* re)
len += snprintf(err_buf+len,2040-len,".");
c_add_message(-1, "SCRIPTING", "Error", err_buf, NULL, 0);
regfree(&myregex);
return 0;
return NULL;
}
res = regexec(&myregex, str, maxn, matches, 0);
lst = mk_nil();
*nmatch = 0;
if (!maxn)
(*nmatch)+= res == 0;
else {
if (maxn) {
dup = strdup(str);
for (i=maxn-1; i>=0; i--) {
if (!res && matches[i].rm_so != -1) {
memcpy(dup, str + matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so);
dup[matches[i].rm_eo - matches[i].rm_so] = '\0';
lst = mk_cons(mk_scon(dup),lst);
(*nmatch)++;
} else {
lst = mk_cons(mk_scon(""),lst);
}
}
free(dup);
}
}
res = regexec(&myregex, str, 1, NULL, 0);

regfree(&myregex);
return res == 0;
return lst;
}

#ifdef __cplusplus
Expand Down

0 comments on commit b62b793

Please sign in to comment.