diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/func.cc | 46 | ||||
-rw-r--r-- | src/lexer.l | 98 |
2 files changed, 120 insertions, 24 deletions
diff --git a/src/func.cc b/src/func.cc index d73b152..7627a94 100644 --- a/src/func.cc +++ b/src/func.cc @@ -125,6 +125,51 @@ Value builtin_sign(const Context *, const QVector<QString>&, const QVector<Value return Value(); } +double frand() +{ + return rand()/(double(RAND_MAX)+1); +} + +double frand(double min, double max) +{ + return (min>max) ? frand()*(min-max)+max : frand()*(max-min)+min; +} + +Value builtin_rands(const Context *, const QVector<QString>&, const QVector<Value> &args) +{ + if (args.size() == 3 && + args[0].type == Value::NUMBER && + args[1].type == Value::NUMBER && + args[2].type == Value::NUMBER) + { + srand((unsigned int)time(0)); + } + else if (args.size() == 4 && + args[0].type == Value::NUMBER && + args[1].type == Value::NUMBER && + args[2].type == Value::NUMBER && + args[3].type == Value::NUMBER) + { + srand((unsigned int)args[3].num); + } + else + { + return Value(); + } + + Value v; + v.type = Value::VECTOR; + + for (int i=0; i<args[2].num; i++) + { + Value * r = new Value(frand(args[0].num, args[1].num)); + v.vec.append(r); + } + + return v; +} + + Value builtin_min(const Context *, const QVector<QString>&, const QVector<Value> &args) { if (args.size() >= 1 && args[0].type == Value::NUMBER) { @@ -298,6 +343,7 @@ void initialize_builtin_functions() { builtin_functions["abs"] = new BuiltinFunction(&builtin_abs); builtin_functions["sign"] = new BuiltinFunction(&builtin_sign); + builtin_functions["rands"] = new BuiltinFunction(&builtin_rands); builtin_functions["min"] = new BuiltinFunction(&builtin_min); builtin_functions["max"] = new BuiltinFunction(&builtin_max); builtin_functions["sin"] = new BuiltinFunction(&builtin_sin); diff --git a/src/lexer.l b/src/lexer.l index 48729c8..9e8aaf8 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -28,9 +28,10 @@ #include "openscad.h" #include "printutils.h" #include "parser_yacc.h" +#include <QStack> #include <QFileInfo> #include <QDir> - +QString* stringcontents; int lexerget_lineno(void); #ifdef __GNUC__ static void yyunput(int, char*) __attribute__((unused)); @@ -58,33 +59,33 @@ extern const char *parser_source_path; } \ } +void includefile(); +QDir sourcepath(); +QStack<QDir> path_stack; + +QString filename; +QString filepath; + %} %option yylineno %option noyywrap -%x comment +%x comment string +%x include + +DIGIT [0-9] %% -include[ \t\r\n>]*"<"[^ \t\r\n>]+">" { - QString filename(yytext); - filename.remove(QRegExp("^include[ \t\r\n>]*<")); - filename.remove(QRegExp(">$")); - QFileInfo finfo(QDir(parser_source_path), filename); - if (!finfo.exists()) { - finfo = QFileInfo(QDir(librarydir), filename); - } - handle_dep(finfo.absoluteFilePath()); - yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); - if (!yyin) { - PRINTA("WARNING: Can't open input file `%1'.", filename); - } else { - yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); - BEGIN(INITIAL); - } +include[ \t\r\n>]*"<" { BEGIN(include); } +<include>{ +[^\t\r\n>]+"/" { filepath = yytext; } +[^\t\r\n>/]+ { filename = yytext; } +">" { BEGIN(INITIAL); includefile(); } } + use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { QString filename(yytext); filename.remove(QRegExp("^use[ \t\r\n>]*<")); @@ -106,7 +107,7 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { finfo = QFileInfo(QDir(librarydir), filename); } - PRINTF("WARNING: Support for implicit include will be removed in future releases. Use `include <filename>' instead."); + PRINTF("DEPRECATED: Support for implicit include will be removed in future releases. Use `include <filename>' instead."); handle_dep(finfo.absoluteFilePath()); yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); if (!yyin) { @@ -119,6 +120,8 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { } <<EOF>> { + if(!path_stack.isEmpty()) + path_stack.pop(); if (yyin && yyin != stdin) fclose(yyin); yypop_buffer_state(); @@ -135,13 +138,21 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { "false" return TOK_FALSE; "undef" return TOK_UNDEF; -[0-9][0-9.]* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } +{DIGIT}+|{DIGIT}*\.{DIGIT}+|{DIGIT}+\.{DIGIT}* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } "$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; } -\"[^"]*\" { - parserlval.text = strdup(yytext+1); - parserlval.text[strlen(parserlval.text)-1] = 0; - return TOK_STRING; +\" { BEGIN(string); stringcontents = new QString(); } +<string>{ +\\n { stringcontents->append('\n'); } +\\t { stringcontents->append('\t'); } +\\r { stringcontents->append('\r'); } +\\\\ { stringcontents->append('\\'); } +\\\" { stringcontents->append('"'); } +[^\\\n\"]+ { stringcontents->append(lexertext); } +\" { BEGIN(INITIAL); + parserlval.text = strdup(stringcontents->toLocal8Bit()); + delete stringcontents; + return TOK_STRING; } } [\n\r\t ] @@ -159,3 +170,42 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { . { return yytext[0]; } +%% + +QDir sourcepath() +{ + if(!path_stack.isEmpty()) + return path_stack.top(); + + return QDir(parser_source_path); +} + +void includefile() +{ + if(filename.isEmpty()) + return; + + if(filepath.isEmpty()) { + path_stack.push(sourcepath()); + } else { + QFileInfo dirinfo(sourcepath(),filepath); + path_stack.push(dirinfo.dir()); + filepath.clear(); + } + + QFileInfo finfo(sourcepath(), filename); + if (!finfo.exists()) { + finfo = QFileInfo(QDir(librarydir), filename); + } + + handle_dep(finfo.absoluteFilePath()); + yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); + if (!yyin) { + PRINTA("WARNING: Can't open input file `%1'.", filename); + return; + } + filename.clear(); + + yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); +} + |