Bladeren bron

allow C and meta to coexist; add @ prefix for meta statements in grammar.

master
Ian Piumarta 3 jaren geleden
bovenliggende
commit
695a9d39df
1 gewijzigde bestanden met toevoegingen van 109 en 62 verwijderingen
  1. +109
    -62
      ccmeta.leg

+ 109
- 62
ccmeta.leg Bestand weergeven

@ -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 = <Space+> { 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 );

Laden…
Annuleren
Opslaan