123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- /* description: Parses openscad to openjscad. */
- /* lexical grammar */
- %lex
- %options flex
- %s cond_include cond_use cond_comment cond_string cond_import
- D [0-9]
- E [Ee][+-]?{D}+
- %%
- /* Note: use and include statements here are ignored. Instead they are preprocessed. */
- include[ \t\r\n>]*"<" %{ this.begin('cond_include'); %}
- <cond_include>[^\t\r\n>]*"/" %{ yy.filepath = yytext; %}
- <cond_include>[^\t\r\n>/]+ %{ yy.filename = yytext; %}
- <cond_include>">" %{ this.popState(); %}
- use[ \t\r\n>]*"<" %{ this.begin('cond_use');%}
- <cond_use>[^\t\r\n>]+ %{ yy.filename = yytext; %}
- <cond_use>">" %{ this.popState(); %}
- "module" return 'TOK_MODULE'
- "function" return 'TOK_FUNCTION'
- "if" return 'TOK_IF'
- "else" return 'TOK_ELSE'
- "true" return 'TOK_TRUE'
- "false" return 'TOK_FALSE'
- "undef" return 'TOK_UNDEF'
- <cond_string>"\\t" %{ stringcontents += ' '; %}
- <cond_string>"\\n" %{ stringcontents += '\n'; %}
- <cond_string>"\\\"" %{ stringcontents += '\"'; %}
- <cond_string>"\\r" %{ stringcontents += '\r'; %}
- <cond_string>"\\\\" %{ stringcontents += '\\'; %}
- <cond_string>"\\0" %{ stringcontents += '\0'; %}
- <cond_string>"\\a" %{ stringcontents += '\a'; %}
- <cond_string>"\\b" %{ stringcontents += '\b'; %}
- <cond_string>"\\t" %{ stringcontents += '\t'; %}
- <cond_string>"\\n" %{ stringcontents += '\n'; %}
- <cond_string>"\\v" %{ stringcontents += '\v'; %}
- <cond_string>"\\f" %{ stringcontents += '\f'; %}
- <cond_string>"\\e" %{ stringcontents += '\e'; %}
- <cond_string>[^\\\n\"]+ %{ /*"*/
- stringcontents += yytext;
- %}
- <cond_string>"\"" %{
- this.popState();
- yytext = stringcontents;
- return 'TOK_STRING';
- %}
- [\"] %{ /*"*/
- this.begin('cond_string');
- stringcontents = "";
- %}
- [\n] /* Ignore */
- [\r\t ] /* Ignore */
- \/\/[^\n]*\n? /* Ignore */
- \/\*.+\*\/ /* Ignore Note: multi-line comments are removed via a preparse regex. */
- {D}*\.{D}+{E}? return 'TOK_NUMBER'
- {D}+\.{D}*{E}? return 'TOK_NUMBER'
- {D}+{E}? return 'TOK_NUMBER'
- "$"?[a-zA-Z0-9_]+ return 'TOK_ID'
- "<=" return 'LE'
- ">=" return 'GE'
- "==" return 'EQ'
- "!=" return 'NE'
- "&&" return 'AND'
- "||" return 'OR'
- . return yytext;
- /lex
- /* operator associations and precedence */
- %right '?' ':'
- %left OR
- %left AND
- %left '<' LE GE '>'
- %left EQ NE
- %left '!' '+' '-'
- %left '*' '/' '%'
- %left '[' ']'
- %left '.'
- %start program
- %% /* language grammar */
- program:
- input
- {
- return ext.processModule(yy);
- }
- ;
- input:
- /* empty */
- | input statement
- ;
- inner_input:
- /* empty */
- | inner_input statement
- ;
- statement:
- statement_begin statement_end
- ;
- statement_begin:
- /*empty*/
- | TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')'
- {
- ext.stashModule($2, $4.argnames, $4.argexpr);
- delete $4;
- }
- ;
- statement_end:
- ';'
- {
- }
- | '{' inner_input '}'
- {
- ext.popModule();
- }
- | module_instantiation
- {
- ext.addModuleChild($1);
- }
- | TOK_ID '=' expr ';'
- {
- ext.addModuleAssignmentVar($1, $3);
- }
- | TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr ';'
- {
- ext.addModuleFunction($2, $8, $4.argnames, $4.argexpr);
- delete $4;
- }
- | BR
- ;
- children_instantiation:
- module_instantiation
- {
- $$ = new ModuleInstantiation();
- if ($1) {
- $$.children.push($1);
- }
- }
- | '{' module_instantiation_list '}'
- {
- $$ = $2;
- }
- ;
- if_statement:
- TOK_IF '(' expr ')' children_instantiation
- {
- $$ = new IfElseModuleInstantiation();
- $$.argnames.push("");
- $$.argexpr.push($3);
- if ($$) {
- $$.children = $5.children;
- } else {
- for (var i = 0; i < $5.children.size(); i++)
- delete $5.children[i];
- }
- delete $5;
- }
- ;
- ifelse_statement:
- if_statement
- {
- $$ = $1;
- }
- | if_statement TOK_ELSE children_instantiation
- {
- $$ = $1;
- if ($$) {
- $$.else_children = $3.children;
- } else {
- for (var i = 0; i < $3.children.size(); i++)
- delete $3.children[i];
- }
- delete $3;
- }
- ;
- module_instantiation:
- single_module_instantiation ';'
- {
- $$ = $1;
- }
- | single_module_instantiation children_instantiation
- {
- $$ = $1;
- if ($$) {
- $$.children = $2.children;
- } else {
- for (var i = 0; i < $2.children.length; i++)
- delete $2.children[i];
- }
- delete $2;
- }
- |
- ifelse_statement
- {
- $$ = $1;
- }
- ;
- module_instantiation_list:
- /* empty */
- {
- $$ = new ModuleInstantiation();
- }
- | module_instantiation_list module_instantiation
- {
- $$ = $1;
- if ($$) {
- if ($2) {
- $$.children.push($2);
- }
- } else {
- delete $2;
- }
- }
- ;
- single_module_instantiation:
- TOK_ID '(' arguments_call ')'
- {
- $$ = new ModuleInstantiation();
- $$.name = $1;
- $$.argnames = $3.argnames;
- $$.argexpr = $3.argexpr;
- delete $3;
- }
- | '!' single_module_instantiation
- {
- $$ = $2;
- if ($$) {
- $$.tag_root = true;
- }
- }
- | '#' single_module_instantiation
- {
- $$ = $2;
- if ($$) {
- $$.tag_highlight = true;
- }
- }
- | '%' single_module_instantiation
- {
- /* - NOTE: Currently unimplemented, therefore not displaying parts marked with %
- $$ = $2;
- if ($$) {
- $$.tag_background = true;
- }
- */
- delete $2;
- $$ = undefined;
- }
- | '*' single_module_instantiation
- {
- delete $2;
- $$ = undefined;
- }
- ;
- expr:
- TOK_TRUE
- {
- $$ = new Expression(true);
- }
- | TOK_FALSE
- {
- $$ = new Expression(false);
- }
- | TOK_UNDEF
- {
- $$ = new Expression(undefined);
- }
- | TOK_ID
- {
- $$ = new Expression();
- $$.type = "L";
- $$.var_name = $1;
- }
- | expr '.' TOK_ID
- {
- $$ = new Expression();
- $$.type = "N";
- $$.children.push($1);
- $$.var_name = $3;
- }
- | TOK_STRING
- {
- $$ = new Expression(String($1));
- }
- | TOK_NUMBER
- {
- $$ = new Expression(Number($1));
- }
- | '[' expr ':' expr ']'
- {
- var e_one = new Expression(1.0);
- $$ = new Expression();
- $$.type = "R";
- $$.children.push($2);
- $$.children.push(e_one);
- $$.children.push($4);
- }
- | '[' expr ':' expr ':' expr ']'
- {
- $$ = new Expression();
- $$.type = "R";
- $$.children.push($2);
- $$.children.push($4);
- $$.children.push($6);
- }
- | '[' optional_commas ']'
- {
- $$ = new Expression([]);
- }
- | '[' vector_expr optional_commas ']'
- {
- $$ = $2;
- }
- | expr '*' expr
- {
- $$ = new Expression();
- $$.type = '*';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr '/' expr
- {
- $$ = new Expression();
- $$.type = '/';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr '%' expr
- {
- $$ = new Expression();
- $$.type = '%';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr '+' expr
- {
- $$ = new Expression();
- $$.type = '+';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr '-' expr
- {
- $$ = new Expression();
- $$.type = '-';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr '<' expr
- {
- $$ = new Expression();
- $$.type = '<';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr LE expr
- {
- $$ = new Expression();
- $$.type = '<=';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr EQ expr
- {
- $$ = new Expression();
- $$.type = '==';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr NE expr
- {
- $$ = new Expression();
- $$.type = '!=';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr GE expr
- {
- $$ = new Expression();
- $$.type = '>=';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr '>' expr
- {
- $$ = new Expression();
- $$.type = '>';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr AND expr
- {
- $$ = new Expression();
- $$.type = '&&';
- $$.children.push($1);
- $$.children.push($3);
- }
- | expr OR expr
- {
- $$ = new Expression();
- $$.type = '||';
- $$.children.push($1);
- $$.children.push($3);
- }
- | '+' expr
- {
- $$ = $2;
- }
- | '-' expr
- {
- $$ = new Expression();
- $$.type = 'I';
- $$.children.push($2);
- }
- | '!' expr
- {
- $$ = new Expression();
- $$.type = '!';
- $$.children.push($2);
- }
- | '(' expr ')'
- { $$ = $2; }
- | expr '?' expr ':' expr
- {
- $$ = new Expression();
- $$.type = '?:';
- $$.children.push($1);
- $$.children.push($3);
- $$.children.push($5);
- }
- | expr '[' expr ']'
- {
- $$ = new Expression();
- $$.type = '[]';
- $$.children.push($1);
- $$.children.push($3);
- }
- | TOK_ID '(' arguments_call ')'
- {
- $$ = new Expression();
- $$.type = 'F';
- $$.call_funcname = $1;
- $$.call_argnames = $3.argnames;
- $$.children = $3.argexpr;
- delete $3;
- }
- ;
- optional_commas:
- ',' optional_commas
- |
- ;
- vector_expr:
- expr
- {
- $$ = new Expression();
- $$.type = 'V';
- $$.children.push($1);
- }
- | vector_expr ',' optional_commas expr
- {
- $$ = $1;
- $$.children.push($4);
- }
- ;
- arguments_decl:
- /* empty */
- {
- $$ = new ArgsContainer();
- }
- | argument_decl
- {
- $$ = new ArgsContainer();
- $$.argnames.push($1.argname);
- $$.argexpr.push($1.argexpr);
- delete $1;
- }
- | arguments_decl ',' optional_commas argument_decl
- {
- $$ = $1;
- $$.argnames.push($4.argname);
- $$.argexpr.push($4.argexpr);
- delete $4;
- }
- ;
- argument_decl:
- TOK_ID
- {
- $$ = new ArgContainer();
- $$.argname = $1;
- $$.argexpr = undefined;
- }
- | TOK_ID '=' expr
- {
- $$ = new ArgContainer();
- $$.argname = $1;
- $$.argexpr = $3;
- }
- ;
- arguments_call:
- /* empty */
- {
- $$ = new ArgsContainer();
- }
- | argument_call
- {
- $$ = new ArgsContainer();
- $$.argnames.push($1.argname);
- $$.argexpr.push($1.argexpr);
- delete $1;
- }
- | arguments_call ',' optional_commas argument_call
- {
- $$ = $1;
- $$.argnames.push($4.argname);
- $$.argexpr.push($4.argexpr);
- delete $4;
- }
- ;
- argument_call:
- expr
- {
- $$ = new ArgContainer();
- $$.argexpr = $1;
- }
- | TOK_ID '=' expr
- {
- $$ = new ArgContainer();
- $$.argname = $1;
- $$.argexpr = $3;
- }
- ;
- %%
|