From 695a9d39dfaa5c6c2d30d8642fd97c85a7339542 Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Mon, 16 Aug 2021 18:58:18 +0900 Subject: [PATCH] allow C and meta to coexist; add @ prefix for meta statements in grammar. --- ccmeta.leg | 171 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 62 deletions(-) diff --git a/ccmeta.leg b/ccmeta.leg index eea80e5..e858ffc 100644 --- a/ccmeta.leg +++ b/ccmeta.leg @@ -3,7 +3,7 @@ # Copyright (c) 2016-2021 Ian Piumarta and other contributors (see AUTHORS) # All rights reserved (see LICENSE) # -# Last edited: 2021-07-12 18:54:53 by piumarta on DESKTOP-LTPREOB +# Last edited: 2021-08-16 18:55:57 by piumarta on DESKTOP-GMTB276 %{ /* compile: leg -o ccmeta.c ccmeta.leg @@ -32,6 +32,8 @@ /* _DO(Quasiquote) _DO(Unquote) */ \ DO_C_PROTOS() +#define META_PROTO_MAX t_Try + #define DO_C_PROTOS() \ _DO(Comment) _DO(Token) \ _DO(C_declaration) _DO(C_string) \ @@ -687,8 +689,8 @@ void C_declarationBegin(void) { typedeffing = 0; } -int C_declarationAbort(void) { - typedeffing = 0; +int C_declarationAbort(void) { + typedeffing = 0; return 0; } @@ -711,14 +713,14 @@ void C_scopeEnd(void) { assert(actualScope); } -int declarationId(char *s) { +int declarationId(char *s) { if (!typedeffing) return 0; addId(s); return 1; } -int isTypedefName(char *s) { - if (!isTypedefed(s)) return 0; +int isTypedefName(char *s) { + if (!isTypedefed(s)) return 0; return 1; } @@ -775,7 +777,7 @@ oop new_C_attributeSpec(oop attributeTok, oop llParen, oop lrParen, oop attribut map_set(object, attributeL_symbol, attributeList); map_set(object, rlparen_symbol, rlParen); map_set(object, rrparen_symbol, rrParen); - return object; + return object; } oop new_C_aggregate(oop lParen, oop typeName, oop rParen, oop leftCurly, oop initList, oop comma, oop rightCurly) { @@ -862,7 +864,7 @@ oop new_C_enumerator(oop id, oop attributeSpecifier, oop expression) { #define YYSTYPE oop -YYSTYPE yylval; +YYSTYPE yylval= 0; int errorLine= 1; @@ -897,6 +899,7 @@ oop newToken(char *text) { oop obj = newObject(Token_proto); map_set(obj, text_symbol, makeString(text)); + icol += strlen(text); return obj; } @@ -1238,12 +1241,26 @@ oop newTry(oop try, oop exception, oop catch, oop finally) return obj; } +enum language { + META = 0, + C = 1, +}; + +enum language lang = C; + %} -#--------------------------------------------- C Grammar -------------------------------------------------# +#--------------------------------------------- C grammar -------------------------------------------------# -start = meta | externalDeclaration +# yylval == null => "pseudo" op, e.g., change language -- ignored by REPL +# yylval == 0 => end of input file while in META mode only + +start = META_AT META_LPAREN s:meta_exp META_RPAREN { yylval= s } + | META_AT META_LCB { yylval= null; lang= META } + | &{ lang == META } - s:meta { yylval= s } + | &{ lang == META } - META_RCB { yylval= null; lang= C } + | &{ lang == C } s:externalDeclaration { yylval= s } error = EOL* < (!EOL .)* EOL* (!EOL .)* > &{ error(yytext), 1 } @@ -1532,7 +1549,7 @@ declaration = @{ C_declarationBegin() } @{ C_declarationEnd() } | &{ C_declarationAbort() } - ) + ) declarationSpecifiers = @{ int specified= 0 } { listBegin() } ( s:storageClassSpecifier { listAppend(s) } @@ -1568,7 +1585,7 @@ functionStorageClassSpecifier = EXTERN | STATIC # 6.7.2 -typeSpecifier = VOID | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE | SIGNED | UNSIGNED | BOOL | COMPLEX +typeSpecifier = VOID | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE | SIGNED | UNSIGNED | BOOL | COMPLEX | ( BUILTIN_VA_LIST | _FLOAT128 ) | structOrUnionSpecifier | enumSpecifier @@ -1643,7 +1660,7 @@ enumerator = i:id # 6.7.3 -typeQualifier = CONST | RESTRICT | VOLATILE +typeQualifier = CONST | RESTRICT | VOLATILE | __RESTRICT # 6.7.4 @@ -1814,7 +1831,7 @@ expressionStatement = SEMI # 6.8.4 -selectionStatement = i:IF l:LPAREN x:expression r:RPAREN s:statement +selectionStatement = i:IF l:LPAREN x:expression r:RPAREN s:statement ( e:ELSE t:statement | {e=t=newNullObject()} ) { $$= new_C_if(i, l, x, r, s, e, t) } | s:SWITCH l:LPAREN x:expression r:RPAREN t:statement { $$= new_C_switch(s, l, x, r, t) } @@ -1839,13 +1856,12 @@ jumpStatement = g:GOTO i:id t:SEMI { $$= new_C_goto(g, newNullObject(), i # 6.9 -translationUnit = externalDeclaration+ +## translationUnit = externalDeclaration+ externalDeclaration = { yylval = newComment(yytext); } | ( SEMI &{gnu} | declaration | functionDefinition - #| meta | &. &{ errmsg= "declaration expected" } error ) { yylval= $$; } @@ -1978,6 +1994,7 @@ COLON = ':' { $$= newToken(":" ) } - COMMA = ',' { $$= newToken("," ) } - QUESTION = '?' { $$= newToken("?" ) } - SEMI = ';' { $$= newToken(";" ) } - + PTR = "->" { $$= newToken("->" ) } - DOT = '.' !'.' { $$= newToken("." ) } - @@ -2084,32 +2101,45 @@ __INLINE = '__inline' !IDREST &{gnu} { $$= newToken("__inlin _FLOAT128 = '_Float128' !IDREST &{gnu} { $$= newToken("_Float128" ) } - +#--------------------------------------------- Common rules ----------------------------------------------# -#--------------------------------------------- Meta Grammar ----------------------------------------------# +- = (blank | comment)* -meta = - ( META_IMPORT s:META_STRING META_SEMICOLON { yylval = null; inputStackPush(get(s, String, value)) } - | s:meta_stmt { yylval = s } - | !. { yylval = 0 } - ) +blank = space | eol +space = [ \t] +eol = ( "\n""\r"* + | "\r""\n"* + ) { inputStack->lineNumber++ } +comment = "//" ( ![\n\r] . )* + | "/*" ( !"*/" (eol | .) )* "*/" -meta_stmt = s:meta_block { $$ = s } - | META_SEMICOLON { $$ = null } - | l:META_IDENT p:meta_paramList e:meta_block { $$ = newFunc(l, p, e, null) } - | META_IF META_LPAREN c:meta_exp META_RPAREN t:meta_stmt META_ELSE f:meta_stmt { $$ = newIf(c, t, f ) } - | META_IF META_LPAREN c:meta_exp META_RPAREN t:meta_stmt { $$ = newIf(c, t, null) } - | META_WHILE META_LPAREN c:meta_exp META_RPAREN s:meta_stmt { $$ = newWhile(c, s) } - | META_DO s:meta_stmt META_WHILE META_LPAREN c:meta_exp META_RPAREN { $$ = newDo(s, c) } - | META_FOR META_LPAREN i:meta_ident META_IN e:meta_exp META_RPAREN s:meta_stmt { $$ = newForIn(i, e, s) } - | META_FOR META_LPAREN i:meta_stmt c:meta_stmt u:meta_exp META_RPAREN s:meta_stmt { $$ = newFor(i, c, u, s) } - | s:meta_switch { $$ = s } - | META_RETURN e:meta_exp { $$ = newReturn(e) } - | META_RETURN { $$ = newReturn(null) } - | META_BREAK { $$ = newBreak() } - | META_CONTINUE { $$ = newContinue() } - | META_THROW e:meta_exp { $$ = newUnary(Throw_proto, e) } - | t:meta_try { $$ = t } - | e:meta_exp META_SEMICOLON { $$ = e } +#--------------------------------------------- Meta grammar ----------------------------------------------# + +# the semicolon has to be explicit with no space eaten afterwards to prevent the +# input buffer from moving past it before redirecting input from the imported file + +meta = META_IMPORT s:META_STRING ";" { $$ = null; inputStackPush(get(s, String, value)) } + | s:meta_stmt { $$ = s } + | !. { $$ = 0 } # signal end of current input file + +meta_stmt = s:meta_block { $$ = s } + | META_SEMICOLON { $$ = null } + | l:META_IDENT p:meta_paramList e:meta_block { $$ = newFunc(l, p, e, null) } + | META_IF META_LPAREN c:meta_exp META_RPAREN t:meta_stmt META_ELSE f:meta_stmt { $$ = newIf(c, t, f ) } + | META_IF META_LPAREN c:meta_exp META_RPAREN t:meta_stmt { $$ = newIf(c, t, null) } + | META_WHILE META_LPAREN c:meta_exp META_RPAREN s:meta_stmt { $$ = newWhile(c, s) } + | META_DO s:meta_stmt META_WHILE META_LPAREN c:meta_exp META_RPAREN { $$ = newDo(s, c) } + | META_FOR META_LPAREN i:meta_ident META_IN e:meta_exp META_RPAREN s:meta_stmt { $$ = newForIn(i, e, s) } + | META_FOR META_LPAREN i:meta_stmt c:meta_stmt u:meta_exp META_RPAREN s:meta_stmt { $$ = newFor(i, c, u, s) } + | s:meta_switch { $$ = s } + | META_RETURN e:meta_exp { $$ = newReturn(e) } + | META_RETURN { $$ = newReturn(null) } + | META_BREAK { $$ = newBreak() } + | META_CONTINUE { $$ = newContinue() } + | META_THROW e:meta_exp { $$ = newUnary(Throw_proto, e) } + | t:meta_try { $$ = t } + | e:meta_exp META_SEMICOLON { $$ = e } meta_block = META_LCB m:meta_makeMap ( s:meta_stmt { map_append(m, s) } @@ -2281,17 +2311,6 @@ meta_makeMap = { $$ = makeMap() } meta_key = META_IDENT | meta_integer -- = (blank | comment)* - -blank = space | eol -space = [ \t] -eol = ( "\n""\r"* - | "\r""\n"* - ) { inputStack->lineNumber++ } - -comment = "//" ( ![\n\r] . )* - | "/*" ( !"*/" (eol | .) )* "*/" - meta_keyword = META_SWITCH | META_CASE | META_DEFAULT | META_DO | META_FOR | META_IN | META_WHILE | META_IF | META_ELSE | META_NULL | META_RETURN | META_BREAK | META_CONTINUE | META_THROW | META_TRY | META_CATCH | META_FINALLY # | META_SYNTAX @@ -2373,7 +2392,7 @@ META_SEMICOLON = ';' - META_COMMA = ',' - META_DOT = '.' - #META_BACKTICK = '`' - -#META_AT = '@' - +META_AT = '@' - META_LCB = '{' - META_RCB = '}' - META_LBRAC = '[' - @@ -3283,7 +3302,7 @@ oop eval(oop scope, oop ast) } #define _DO(NAME) case t_##NAME: DO_C_PROTOS(); - break; + break; #undef _DO } printf("EVAL "); @@ -3376,6 +3395,9 @@ oop evalArgs(oop scope, oop args) } oop AST= NULL; +oop outputProgram= 0; + +void outputNode(oop node); void readEvalPrint(oop scope, char *fileName) { @@ -3387,14 +3409,33 @@ void readEvalPrint(oop scope, char *fileName) if (0 == jbt) { while (yyparse()) { - if (opt_v > 1) printf("%s:%i: ", get(inputStack->name, String, value), inputStack->lineNumber); - if (!yylval) { + if (!yylval) { // EOF fclose(inputStack->file); if (top == inputStack) break; inputStackPop(); assert(inputStack); continue; - } // EOF + } + assert(yylval); + if (null == yylval) { // change of language or input file + continue; + } + oop proto = map_get(yylval, __proto___symbol); + if (proto == null) { + printf("no prototype associated with "); + println(yylval); + fflush(stdout); + fprintf(stderr, "aborting\n"); + exit(1); + } + // proto_number is the enum version of the proto symbol + proto_t proto_number = get(map_get(proto, __name___symbol), Symbol, prototype); + if (proto_number > META_PROTO_MAX) { + if (opt_v > 1) println(yylval); + map_append(outputProgram, yylval); + continue; + } + if (opt_v > 1) printf("%s:%i: ", get(inputStack->name, String, value), inputStack->lineNumber); if (opt_v > 1) println(yylval); oop res = eval(scope, yylval); if (opt_v > 0) println(res); @@ -3613,15 +3654,15 @@ void outputNode(oop node) case t_C_prefix: outputNode(map_get(node, operator_symbol)); outputNode(map_get(node, expression_symbol)); - break; + break; case t_C_postfix: outputNode(map_get(node, expression_symbol)); outputNode(map_get(node, operator_symbol)); - break; + break; case t_C_unary: outputNode(map_get(node, operator_symbol)); outputNode(map_get(node, expression_symbol)); - break; + break; case t_C_binary: outputNode(map_get(node, lhs_symbol)); outputNode(map_get(node, binary_symbol)); @@ -3828,7 +3869,7 @@ void outputValue(oop node) { void printSpace(int depth) { for (int i = 0 ; i < depth ; i++) { printf(" "); - } + } } void outputTree(oop node, int depth) @@ -3893,7 +3934,7 @@ void outputTree(oop node, int depth) OUT(consequent); OUT(elseTok); OUT(alternate); - break; + break; CASE(while) OUT(whileTok); OUT(lparen); @@ -3986,15 +4027,15 @@ void outputTree(oop node, int depth) CASE(prefix) OUT(operator); OUT(expression); - break; + break; CASE(postfix) OUT(expression); OUT(operator); - break; + break; CASE(unary) OUT(operator); OUT(expression); - break; + break; CASE(binary) OUT(lhs); OUT(binary); @@ -4190,6 +4231,7 @@ int main(int argc, char **argv) symbol_table= makeMap(); globals= makeMap(); + outputProgram= makeMap(); map_set(globals, intern("exit" ), makeFunction(prim_exit, intern("exit" ), null, null, globals, null)); map_set(globals, intern("keys" ), makeFunction(prim_keys, intern("keys" ), null, null, globals, null)); @@ -4259,6 +4301,11 @@ int main(int argc, char **argv) readEvalPrint(globals, NULL); } + for (size_t i= 0; i < map_size(outputProgram); ++i) { + oop element= get(outputProgram, Map, elements)[i].value; + outputNode(element); + } + if (opt_g) { if (nalloc < 1024) printf("[GC: %lli bytes allocated]\n", nalloc ); else if (nalloc < 1024*1024) printf("[GC: %lli kB allocated]\n", nalloc / 1024 );