From 07f7fb9d520da716a0d2d9890239bccfa7b0bd47 Mon Sep 17 00:00:00 2001 From: Markus Pfeiffer Date: Wed, 25 Oct 2017 00:55:19 +0100 Subject: [PATCH] Introduce #@ pragmas This is an experimental syntax extension to add arbitrary annotations into statement sequences. This, together with the syntaxtree module will enable users to process GAP source without writing their own ad-hoc parsers. --- src/code.c | 11 +++++++ src/code.h | 4 +++ src/intrprtr.c | 10 +++++++ src/intrprtr.h | 2 ++ src/read.c | 80 ++++++++++++++++++++++++++++++++++---------------- src/scanner.c | 32 ++++++++++++++++---- src/stats.c | 12 ++++++++ 7 files changed, 121 insertions(+), 30 deletions(-) diff --git a/src/code.c b/src/code.c index 14dc42334d..95f7b638b4 100644 --- a/src/code.c +++ b/src/code.c @@ -886,6 +886,17 @@ void CodeFuncExprEnd ( } +void CodePragma(Obj content) +{ + Stat pragma; + + pragma = NewStat( T_PRAGMA, SIZEBAG_STRINGLEN(GET_LEN_STRING(content)) ); + memcpy( (void *)ADDR_STAT(pragma), CONST_ADDR_OBJ(content), + SIZEBAG_STRINGLEN(GET_LEN_STRING(content)) ); + + PushStat( pragma ); +} + /**************************************************************************** ** diff --git a/src/code.h b/src/code.h index 147e0cebd8..a5a5fbcbf1 100644 --- a/src/code.h +++ b/src/code.h @@ -220,6 +220,8 @@ enum STAT_TNUMS { T_ASSERT_2ARGS, T_ASSERT_3ARGS, + T_PRAGMA, + END_ENUM_RANGE(LAST_STAT_TNUM), }; @@ -1401,6 +1403,8 @@ extern void CodeAssertEnd3Args ( void ); /* CodeContinue() . . . . . . . . . . . . . code continue-statement */ extern void CodeContinue ( void ); +extern void CodePragma(Obj pragma); + /**************************************************************************** ** *V FilenameCache . . . . . . . . . . . . . . . . . . list of filenames diff --git a/src/intrprtr.c b/src/intrprtr.c index fc1bc9576b..e6dc4da835 100644 --- a/src/intrprtr.c +++ b/src/intrprtr.c @@ -300,6 +300,16 @@ ExecStatus IntrEnd ( } +/* Interpret a pragma, that is, if we're coding, code it, otherwise + ignore it */ +void IntrPragma(Obj pragma) +{ + /* ignore or code */ + if ( STATE(IntrReturning) > 0 ) { return; } + if ( STATE(IntrIgnoring) > 0 ) { return; } + if ( STATE(IntrCoding) > 0 ) { CodePragma(pragma); return; } +} + /**************************************************************************** ** *F IntrFuncCallBegin() . . . . . . . . . . . interpret function call, begin diff --git a/src/intrprtr.h b/src/intrprtr.h index 60c99731fa..5b9a868489 100644 --- a/src/intrprtr.h +++ b/src/intrprtr.h @@ -977,6 +977,8 @@ extern void IntrSaveWSEnd ( void ); */ extern void IntrContinue ( void ); +extern void IntrPragma(Obj pragma); + /**************************************************************************** *F PushVoidObj() . . . . . . . . . . . . . . push void value onto the stack */ diff --git a/src/read.c b/src/read.c index a5afb9b493..762ff2050d 100644 --- a/src/read.c +++ b/src/read.c @@ -2572,6 +2572,18 @@ void ReadReturn ( } } +void ReadPragma(TypSymbolSet follow) +{ + Obj pragma; + UInt len; + + C_NEW_STRING( pragma, STATE(ValueLen), (void *)STATE(Value) ); + len = STATE(ValueLen); + SET_LEN_STRING(pragma, len); + *(CHARS_STRING(pragma) + len) = 0; + Match(S_PRAGMA, "pragma", follow); + IntrPragma( pragma ); +} /**************************************************************************** ** @@ -2657,37 +2669,55 @@ void ReadQUIT ( ** | 'atomic' { ',' } 'do' 'od' ';' ** | ';' */ -UInt ReadStats ( - TypSymbolSet follow ) +UInt ReadStats(TypSymbolSet follow) { - UInt nr; /* number of statements */ + UInt nr; /* number of statements */ - /* read the statements */ nr = 0; - while ( IS_IN( STATE(Symbol), STATBEGIN|S_SEMICOLON ) ) { - - /* read a statement */ - if ( STATE(Symbol) == S_IDENT ) ReadCallVarAss(follow,'s'); - else if ( STATE(Symbol) == S_UNBIND ) ReadUnbind( follow ); - else if ( STATE(Symbol) == S_INFO ) ReadInfo( follow ); - else if ( STATE(Symbol) == S_ASSERT ) ReadAssert( follow ); - else if ( STATE(Symbol) == S_IF ) ReadIf( follow ); - else if ( STATE(Symbol) == S_FOR ) ReadFor( follow ); - else if ( STATE(Symbol) == S_WHILE ) ReadWhile( follow ); - else if ( STATE(Symbol) == S_REPEAT ) ReadRepeat( follow ); - else if ( STATE(Symbol) == S_BREAK ) ReadBreak( follow ); - else if ( STATE(Symbol) == S_CONTINUE) ReadContinue( follow ); - else if ( STATE(Symbol) == S_RETURN ) ReadReturn( follow ); - else if ( STATE(Symbol) == S_TRYNEXT) ReadTryNext( follow ); - else if ( STATE(Symbol) == S_QUIT ) ReadQuit( follow ); - else if ( STATE(Symbol) == S_ATOMIC ) ReadAtomic( follow ); - else ReadEmpty( follow ); - nr++; - Match( S_SEMICOLON, ";", follow ); + while (IS_IN(STATE(Symbol), STATBEGIN | S_SEMICOLON)) { + if (STATE(Symbol) == S_PRAGMA) + ReadPragma(follow); + else { + /* read a statement */ + if (STATE(Symbol) == S_IDENT) + ReadCallVarAss(follow, 's'); + else if (STATE(Symbol) == S_UNBIND) + ReadUnbind(follow); + else if (STATE(Symbol) == S_INFO) + ReadInfo(follow); + else if (STATE(Symbol) == S_ASSERT) + ReadAssert(follow); + else if (STATE(Symbol) == S_IF) + ReadIf(follow); + else if (STATE(Symbol) == S_FOR) + ReadFor(follow); + else if (STATE(Symbol) == S_WHILE) + ReadWhile(follow); + else if (STATE(Symbol) == S_REPEAT) + ReadRepeat(follow); + else if (STATE(Symbol) == S_BREAK) + ReadBreak(follow); + else if (STATE(Symbol) == S_CONTINUE) + ReadContinue(follow); + else if (STATE(Symbol) == S_RETURN) + ReadReturn(follow); + else if (STATE(Symbol) == S_TRYNEXT) + ReadTryNext(follow); + else if (STATE(Symbol) == S_QUIT) + ReadQuit(follow); + else if (STATE(Symbol) == S_ATOMIC) + ReadAtomic(follow); + else if (STATE(Symbol) == S_PRAGMA) + ReadPragma(follow); + else + ReadEmpty(follow); + Match(S_SEMICOLON, ";", follow); + } + nr++; } - /* return the number of statements */ + /* return the number of statements */ return nr; } diff --git a/src/scanner.c b/src/scanner.c index c97117bc73..9adb27c23c 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -2105,6 +2105,22 @@ void GetChar ( void ) } } +void GetPragma(void) +{ + Int i = 0; + + /* Skip @ */ + GET_CHAR(); + while (*STATE(In) != '\n' && *STATE(In) != '\r' && + *STATE(In) != '\377') { + STATE(Value)[i] = *STATE(In); + i++; + GET_CHAR(); + } + STATE(Value)[i] = '\0'; + STATE(ValueLen) = i; +} + /**************************************************************************** ** *F GetSymbol() . . . . . . . . . . . . . . . . . get the next symbol, local @@ -2151,20 +2167,26 @@ void GetSymbol ( void ) GET_CHAR(); } - /* skip over , , and comments */ + /* skip over , , and */ while (*STATE(In) == ' ' || *STATE(In) == '\t' || *STATE(In) == '\n' || *STATE(In) == '\r' || *STATE(In) == '\f' || *STATE(In) == '#') { if (*STATE(In) == '#') { - while (*STATE(In) != '\n' && *STATE(In) != '\r' && - *STATE(In) != '\377') - GET_CHAR(); + GET_CHAR(); + if (*STATE(In) == '@') { + STATE(Symbol) = S_PRAGMA; + GetPragma(); + return; + } else { + while (*STATE(In) != '\n' && *STATE(In) != '\r' && + *STATE(In) != '\377') + GET_CHAR(); + } } GET_CHAR(); } /* switch according to the character */ switch (*STATE(In)) { - case '.': STATE(Symbol) = S_DOT; GET_CHAR(); diff --git a/src/stats.c b/src/stats.c index 44953e931a..067d9c1ef4 100644 --- a/src/stats.c +++ b/src/stats.c @@ -2009,6 +2009,17 @@ void PrintAtomic ( Pr( "%4<\nod;", 0L, 0L ); } +void PrintPragma(Stat stat) +{ + Char *pragma; + + /* TODO: super ugly */ + pragma = (Char *)((UInt *)(&ADDR_STAT(stat)[1])); + + Pr("#@", 0L, 0L); + Pr("%s", (Int)(pragma), 0L); +} + /**************************************************************************** ** @@ -2309,6 +2320,7 @@ static Int InitKernel ( InstallPrintStatFunc( T_RETURN_VOID , PrintReturnVoid); InstallPrintStatFunc( T_EMPTY , PrintEmpty); InstallPrintStatFunc( T_ATOMIC , PrintAtomic); + InstallPrintStatFunc( T_PRAGMA , PrintPragma); for ( i = 0; i < ARRAY_SIZE(ExecStatFuncs); i++ ) IntrExecStatFuncs[i] = ExecIntrStat;