mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-10-21 02:24:34 +00:00
Added support for #if reusing the expression parser. Added support for the special defined operator. Now using the base parser for the preprocessor test. #169
This commit is contained in:
parent
0a11eefda0
commit
4352874305
@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||
import dk.camelot64.kickc.model.values.ConstantEnumerable;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
|
||||
/** Unary Logic Not operator (!b) */
|
||||
@ -15,6 +16,9 @@ public class OperatorLogicNot extends OperatorUnary {
|
||||
|
||||
@Override
|
||||
public ConstantLiteral calculateLiteral(ConstantLiteral left, ProgramScope scope) {
|
||||
if(left instanceof ConstantEnumerable) {
|
||||
left = new ConstantBool(((ConstantEnumerable) left).getInteger()!=0);
|
||||
}
|
||||
if(left instanceof ConstantBool) {
|
||||
return new ConstantBool(!((ConstantBool) left).getBool() );
|
||||
}
|
||||
|
@ -4,16 +4,12 @@ import dk.camelot64.kickc.SourceLoader;
|
||||
import dk.camelot64.kickc.preprocessor.CPreprocessor;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.preprocessor.CPreprocessorTokens;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Parser for C-language files.
|
||||
@ -65,8 +61,7 @@ public class CParser {
|
||||
this.program = program;
|
||||
this.cFiles = new LinkedHashMap<>();
|
||||
this.cTokenSource = new CTokenSource();
|
||||
final CPreprocessorTokens preprocessorTokens = new CPreprocessorTokens(CHANNEL_WHITESPACE, KickCLexer.WS, KickCLexer.DEFINE, KickCLexer.NAME, KickCLexer.DEFINE_CONTINUE, KickCLexer.UNDEF, KickCLexer.IFDEF, KickCLexer.IFNDEF, KickCLexer.IFELSE, KickCLexer.ENDIF, KickCLexer.PAR_BEGIN, KickCLexer.PAR_END, KickCLexer.COMMA);
|
||||
final CPreprocessor preprocessor = new CPreprocessor(cTokenSource, preprocessorTokens);
|
||||
final CPreprocessor preprocessor = new CPreprocessor(cTokenSource, new HashMap<>());
|
||||
this.tokenStream = new CommonTokenStream(preprocessor);
|
||||
this.parser = new KickCParser(tokenStream, this);
|
||||
this.typedefs = new ArrayList<>();
|
||||
@ -115,6 +110,14 @@ public class CParser {
|
||||
return this.parser.file();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C parser
|
||||
* @return The C parser
|
||||
*/
|
||||
public KickCParser getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path of the folder containing the source file for a token
|
||||
*
|
||||
@ -179,7 +182,21 @@ public class CParser {
|
||||
program.getLog().append("PARSING " + file.getPath().replace("\\", "/"));
|
||||
program.getLog().append(fileStream.toString());
|
||||
}
|
||||
KickCLexer lexer = new KickCLexer(fileStream, this);
|
||||
KickCLexer lexer = addSource(fileStream);
|
||||
CFile cFile = new CFile(file, lexer);
|
||||
cFiles.put(file.getAbsolutePath(), cFile);
|
||||
} catch(IOException e) {
|
||||
throw new CompileError("Error parsing file " + fileName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add source code at the start of the token stream being parsed.
|
||||
* @param charStream The char stream containing the source code to add
|
||||
* @return The lexer for reading the source tokens of the added source
|
||||
*/
|
||||
public KickCLexer addSource(CharStream charStream) {
|
||||
KickCLexer lexer = new KickCLexer(charStream, this);
|
||||
lexer.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
public void syntaxError(
|
||||
@ -189,15 +206,11 @@ public class CParser {
|
||||
int charPositionInLine,
|
||||
String msg,
|
||||
RecognitionException e) {
|
||||
throw new CompileError("Error parsing file " + fileStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
throw new CompileError("Error parsing file " + charStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
}
|
||||
});
|
||||
CFile cFile = new CFile(file, lexer);
|
||||
cFiles.put(file.getAbsolutePath(), cFile);
|
||||
cTokenSource.addSource(lexer);
|
||||
} catch(IOException e) {
|
||||
throw new CompileError("Error parsing file " + fileName, e);
|
||||
}
|
||||
return lexer;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ STRUCT : 'struct' ;
|
||||
ENUM : 'enum' ;
|
||||
SIZEOF : 'sizeof' ;
|
||||
TYPEID : 'typeid' ;
|
||||
DEFINED : 'defined' ;
|
||||
KICKASM : 'kickasm' ;
|
||||
RESOURCE : 'resource' ;
|
||||
USES : 'uses' ;
|
||||
@ -124,10 +125,12 @@ CHAR : '\'' ('\\'['"rfn] | ~'\'' ) '\'';
|
||||
|
||||
// Macros
|
||||
DEFINE: '#define' ;
|
||||
DEFINE_CONTINUE: '\\\n' ;
|
||||
DEFINE_CONTINUE: '\\\n' | '\\\r\n';
|
||||
UNDEF: '#undef' ;
|
||||
IFDEF: '#ifdef' ;
|
||||
IFNDEF: '#ifndef' ;
|
||||
IFIF: '#if' ;
|
||||
ELIF: '#elif' ;
|
||||
IFELSE: '#else' ;
|
||||
ENDIF: '#endif' ;
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -79,75 +79,78 @@ STRUCT=78
|
||||
ENUM=79
|
||||
SIZEOF=80
|
||||
TYPEID=81
|
||||
KICKASM=82
|
||||
RESOURCE=83
|
||||
USES=84
|
||||
CLOBBERS=85
|
||||
BYTES=86
|
||||
CYCLES=87
|
||||
LOGIC_NOT=88
|
||||
SIGNEDNESS=89
|
||||
SIMPLETYPE=90
|
||||
BOOLEAN=91
|
||||
KICKASM_BODY=92
|
||||
STRING=93
|
||||
CHAR=94
|
||||
DEFINE=95
|
||||
DEFINE_CONTINUE=96
|
||||
UNDEF=97
|
||||
IFDEF=98
|
||||
IFNDEF=99
|
||||
IFELSE=100
|
||||
ENDIF=101
|
||||
NUMBER=102
|
||||
NUMFLOAT=103
|
||||
BINFLOAT=104
|
||||
DECFLOAT=105
|
||||
HEXFLOAT=106
|
||||
NUMINT=107
|
||||
BININTEGER=108
|
||||
DECINTEGER=109
|
||||
HEXINTEGER=110
|
||||
NAME=111
|
||||
WS=112
|
||||
COMMENT_LINE=113
|
||||
COMMENT_BLOCK=114
|
||||
ASM_BYTE=115
|
||||
ASM_MNEMONIC=116
|
||||
ASM_IMM=117
|
||||
ASM_COLON=118
|
||||
ASM_COMMA=119
|
||||
ASM_PAR_BEGIN=120
|
||||
ASM_PAR_END=121
|
||||
ASM_BRACKET_BEGIN=122
|
||||
ASM_BRACKET_END=123
|
||||
ASM_DOT=124
|
||||
ASM_SHIFT_LEFT=125
|
||||
ASM_SHIFT_RIGHT=126
|
||||
ASM_PLUS=127
|
||||
ASM_MINUS=128
|
||||
ASM_LESS_THAN=129
|
||||
ASM_GREATER_THAN=130
|
||||
ASM_MULTIPLY=131
|
||||
ASM_DIVIDE=132
|
||||
ASM_CURLY_BEGIN=133
|
||||
ASM_CURLY_END=134
|
||||
ASM_NUMBER=135
|
||||
ASM_NUMFLOAT=136
|
||||
ASM_BINFLOAT=137
|
||||
ASM_DECFLOAT=138
|
||||
ASM_HEXFLOAT=139
|
||||
ASM_NUMINT=140
|
||||
ASM_BININTEGER=141
|
||||
ASM_DECINTEGER=142
|
||||
ASM_HEXINTEGER=143
|
||||
ASM_CHAR=144
|
||||
ASM_MULTI_REL=145
|
||||
ASM_MULTI_NAME=146
|
||||
ASM_NAME=147
|
||||
ASM_WS=148
|
||||
ASM_COMMENT_LINE=149
|
||||
ASM_COMMENT_BLOCK=150
|
||||
DEFINED=82
|
||||
KICKASM=83
|
||||
RESOURCE=84
|
||||
USES=85
|
||||
CLOBBERS=86
|
||||
BYTES=87
|
||||
CYCLES=88
|
||||
LOGIC_NOT=89
|
||||
SIGNEDNESS=90
|
||||
SIMPLETYPE=91
|
||||
BOOLEAN=92
|
||||
KICKASM_BODY=93
|
||||
STRING=94
|
||||
CHAR=95
|
||||
DEFINE=96
|
||||
DEFINE_CONTINUE=97
|
||||
UNDEF=98
|
||||
IFDEF=99
|
||||
IFNDEF=100
|
||||
IFIF=101
|
||||
ELIF=102
|
||||
IFELSE=103
|
||||
ENDIF=104
|
||||
NUMBER=105
|
||||
NUMFLOAT=106
|
||||
BINFLOAT=107
|
||||
DECFLOAT=108
|
||||
HEXFLOAT=109
|
||||
NUMINT=110
|
||||
BININTEGER=111
|
||||
DECINTEGER=112
|
||||
HEXINTEGER=113
|
||||
NAME=114
|
||||
WS=115
|
||||
COMMENT_LINE=116
|
||||
COMMENT_BLOCK=117
|
||||
ASM_BYTE=118
|
||||
ASM_MNEMONIC=119
|
||||
ASM_IMM=120
|
||||
ASM_COLON=121
|
||||
ASM_COMMA=122
|
||||
ASM_PAR_BEGIN=123
|
||||
ASM_PAR_END=124
|
||||
ASM_BRACKET_BEGIN=125
|
||||
ASM_BRACKET_END=126
|
||||
ASM_DOT=127
|
||||
ASM_SHIFT_LEFT=128
|
||||
ASM_SHIFT_RIGHT=129
|
||||
ASM_PLUS=130
|
||||
ASM_MINUS=131
|
||||
ASM_LESS_THAN=132
|
||||
ASM_GREATER_THAN=133
|
||||
ASM_MULTIPLY=134
|
||||
ASM_DIVIDE=135
|
||||
ASM_CURLY_BEGIN=136
|
||||
ASM_CURLY_END=137
|
||||
ASM_NUMBER=138
|
||||
ASM_NUMFLOAT=139
|
||||
ASM_BINFLOAT=140
|
||||
ASM_DECFLOAT=141
|
||||
ASM_HEXFLOAT=142
|
||||
ASM_NUMINT=143
|
||||
ASM_BININTEGER=144
|
||||
ASM_DECINTEGER=145
|
||||
ASM_HEXINTEGER=146
|
||||
ASM_CHAR=147
|
||||
ASM_MULTI_REL=148
|
||||
ASM_MULTI_NAME=149
|
||||
ASM_NAME=150
|
||||
ASM_WS=151
|
||||
ASM_COMMENT_LINE=152
|
||||
ASM_COMMENT_BLOCK=153
|
||||
';'=8
|
||||
'..'=11
|
||||
'?'=12
|
||||
@ -209,19 +212,21 @@ ASM_COMMENT_BLOCK=150
|
||||
'enum'=79
|
||||
'sizeof'=80
|
||||
'typeid'=81
|
||||
'kickasm'=82
|
||||
'resource'=83
|
||||
'uses'=84
|
||||
'clobbers'=85
|
||||
'bytes'=86
|
||||
'cycles'=87
|
||||
'!'=88
|
||||
'#define'=95
|
||||
'\\\n'=96
|
||||
'#undef'=97
|
||||
'#ifdef'=98
|
||||
'#ifndef'=99
|
||||
'#else'=100
|
||||
'#endif'=101
|
||||
'.byte'=115
|
||||
'#'=117
|
||||
'defined'=82
|
||||
'kickasm'=83
|
||||
'resource'=84
|
||||
'uses'=85
|
||||
'clobbers'=86
|
||||
'bytes'=87
|
||||
'cycles'=88
|
||||
'!'=89
|
||||
'#define'=96
|
||||
'#undef'=98
|
||||
'#ifdef'=99
|
||||
'#ifndef'=100
|
||||
'#if'=101
|
||||
'#elif'=102
|
||||
'#else'=103
|
||||
'#endif'=104
|
||||
'.byte'=118
|
||||
'#'=120
|
||||
|
@ -220,6 +220,7 @@ expr
|
||||
| expr PAR_BEGIN parameterList? PAR_END #exprCall
|
||||
| SIZEOF PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprSizeOf
|
||||
| TYPEID PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprTypeId
|
||||
| DEFINED PAR_BEGIN? NAME PAR_END? #exprDefined
|
||||
| expr BRACKET_BEGIN commaExpr BRACKET_END #exprArray
|
||||
| PAR_BEGIN typeSpecifier PAR_END expr #exprCast
|
||||
| ('--' | '++' ) expr #exprPreMod
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -79,75 +79,78 @@ STRUCT=78
|
||||
ENUM=79
|
||||
SIZEOF=80
|
||||
TYPEID=81
|
||||
KICKASM=82
|
||||
RESOURCE=83
|
||||
USES=84
|
||||
CLOBBERS=85
|
||||
BYTES=86
|
||||
CYCLES=87
|
||||
LOGIC_NOT=88
|
||||
SIGNEDNESS=89
|
||||
SIMPLETYPE=90
|
||||
BOOLEAN=91
|
||||
KICKASM_BODY=92
|
||||
STRING=93
|
||||
CHAR=94
|
||||
DEFINE=95
|
||||
DEFINE_CONTINUE=96
|
||||
UNDEF=97
|
||||
IFDEF=98
|
||||
IFNDEF=99
|
||||
IFELSE=100
|
||||
ENDIF=101
|
||||
NUMBER=102
|
||||
NUMFLOAT=103
|
||||
BINFLOAT=104
|
||||
DECFLOAT=105
|
||||
HEXFLOAT=106
|
||||
NUMINT=107
|
||||
BININTEGER=108
|
||||
DECINTEGER=109
|
||||
HEXINTEGER=110
|
||||
NAME=111
|
||||
WS=112
|
||||
COMMENT_LINE=113
|
||||
COMMENT_BLOCK=114
|
||||
ASM_BYTE=115
|
||||
ASM_MNEMONIC=116
|
||||
ASM_IMM=117
|
||||
ASM_COLON=118
|
||||
ASM_COMMA=119
|
||||
ASM_PAR_BEGIN=120
|
||||
ASM_PAR_END=121
|
||||
ASM_BRACKET_BEGIN=122
|
||||
ASM_BRACKET_END=123
|
||||
ASM_DOT=124
|
||||
ASM_SHIFT_LEFT=125
|
||||
ASM_SHIFT_RIGHT=126
|
||||
ASM_PLUS=127
|
||||
ASM_MINUS=128
|
||||
ASM_LESS_THAN=129
|
||||
ASM_GREATER_THAN=130
|
||||
ASM_MULTIPLY=131
|
||||
ASM_DIVIDE=132
|
||||
ASM_CURLY_BEGIN=133
|
||||
ASM_CURLY_END=134
|
||||
ASM_NUMBER=135
|
||||
ASM_NUMFLOAT=136
|
||||
ASM_BINFLOAT=137
|
||||
ASM_DECFLOAT=138
|
||||
ASM_HEXFLOAT=139
|
||||
ASM_NUMINT=140
|
||||
ASM_BININTEGER=141
|
||||
ASM_DECINTEGER=142
|
||||
ASM_HEXINTEGER=143
|
||||
ASM_CHAR=144
|
||||
ASM_MULTI_REL=145
|
||||
ASM_MULTI_NAME=146
|
||||
ASM_NAME=147
|
||||
ASM_WS=148
|
||||
ASM_COMMENT_LINE=149
|
||||
ASM_COMMENT_BLOCK=150
|
||||
DEFINED=82
|
||||
KICKASM=83
|
||||
RESOURCE=84
|
||||
USES=85
|
||||
CLOBBERS=86
|
||||
BYTES=87
|
||||
CYCLES=88
|
||||
LOGIC_NOT=89
|
||||
SIGNEDNESS=90
|
||||
SIMPLETYPE=91
|
||||
BOOLEAN=92
|
||||
KICKASM_BODY=93
|
||||
STRING=94
|
||||
CHAR=95
|
||||
DEFINE=96
|
||||
DEFINE_CONTINUE=97
|
||||
UNDEF=98
|
||||
IFDEF=99
|
||||
IFNDEF=100
|
||||
IFIF=101
|
||||
ELIF=102
|
||||
IFELSE=103
|
||||
ENDIF=104
|
||||
NUMBER=105
|
||||
NUMFLOAT=106
|
||||
BINFLOAT=107
|
||||
DECFLOAT=108
|
||||
HEXFLOAT=109
|
||||
NUMINT=110
|
||||
BININTEGER=111
|
||||
DECINTEGER=112
|
||||
HEXINTEGER=113
|
||||
NAME=114
|
||||
WS=115
|
||||
COMMENT_LINE=116
|
||||
COMMENT_BLOCK=117
|
||||
ASM_BYTE=118
|
||||
ASM_MNEMONIC=119
|
||||
ASM_IMM=120
|
||||
ASM_COLON=121
|
||||
ASM_COMMA=122
|
||||
ASM_PAR_BEGIN=123
|
||||
ASM_PAR_END=124
|
||||
ASM_BRACKET_BEGIN=125
|
||||
ASM_BRACKET_END=126
|
||||
ASM_DOT=127
|
||||
ASM_SHIFT_LEFT=128
|
||||
ASM_SHIFT_RIGHT=129
|
||||
ASM_PLUS=130
|
||||
ASM_MINUS=131
|
||||
ASM_LESS_THAN=132
|
||||
ASM_GREATER_THAN=133
|
||||
ASM_MULTIPLY=134
|
||||
ASM_DIVIDE=135
|
||||
ASM_CURLY_BEGIN=136
|
||||
ASM_CURLY_END=137
|
||||
ASM_NUMBER=138
|
||||
ASM_NUMFLOAT=139
|
||||
ASM_BINFLOAT=140
|
||||
ASM_DECFLOAT=141
|
||||
ASM_HEXFLOAT=142
|
||||
ASM_NUMINT=143
|
||||
ASM_BININTEGER=144
|
||||
ASM_DECINTEGER=145
|
||||
ASM_HEXINTEGER=146
|
||||
ASM_CHAR=147
|
||||
ASM_MULTI_REL=148
|
||||
ASM_MULTI_NAME=149
|
||||
ASM_NAME=150
|
||||
ASM_WS=151
|
||||
ASM_COMMENT_LINE=152
|
||||
ASM_COMMENT_BLOCK=153
|
||||
';'=8
|
||||
'..'=11
|
||||
'?'=12
|
||||
@ -209,19 +212,21 @@ ASM_COMMENT_BLOCK=150
|
||||
'enum'=79
|
||||
'sizeof'=80
|
||||
'typeid'=81
|
||||
'kickasm'=82
|
||||
'resource'=83
|
||||
'uses'=84
|
||||
'clobbers'=85
|
||||
'bytes'=86
|
||||
'cycles'=87
|
||||
'!'=88
|
||||
'#define'=95
|
||||
'\\\n'=96
|
||||
'#undef'=97
|
||||
'#ifdef'=98
|
||||
'#ifndef'=99
|
||||
'#else'=100
|
||||
'#endif'=101
|
||||
'.byte'=115
|
||||
'#'=117
|
||||
'defined'=82
|
||||
'kickasm'=83
|
||||
'resource'=84
|
||||
'uses'=85
|
||||
'clobbers'=86
|
||||
'bytes'=87
|
||||
'cycles'=88
|
||||
'!'=89
|
||||
'#define'=96
|
||||
'#undef'=98
|
||||
'#ifdef'=99
|
||||
'#ifndef'=100
|
||||
'#if'=101
|
||||
'#elif'=102
|
||||
'#else'=103
|
||||
'#endif'=104
|
||||
'.byte'=118
|
||||
'#'=120
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.7.2
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickCParser.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parser;
|
||||
|
||||
|
||||
@ -1273,6 +1273,18 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprId(KickCParser.ExprIdContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprDefined(KickCParser.ExprDefinedContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprDefined(KickCParser.ExprDefinedContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.7.2
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickCParser.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parser;
|
||||
|
||||
|
||||
@ -748,6 +748,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprId(KickCParser.ExprIdContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprDefined(KickCParser.ExprDefinedContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.7.2
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickCParser.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parser;
|
||||
|
||||
|
||||
@ -1221,6 +1221,18 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprId(KickCParser.ExprIdContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprDefined}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprDefined(KickCParser.ExprDefinedContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprDefined}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprDefined(KickCParser.ExprDefinedContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprTernary}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.7.2
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickCParser.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parser;
|
||||
|
||||
|
||||
@ -723,6 +723,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprId(KickCParser.ExprIdContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprDefined}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprDefined(KickCParser.ExprDefinedContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprTernary}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
|
@ -1,8 +1,17 @@
|
||||
package dk.camelot64.kickc.preprocessor;
|
||||
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.parser.CTokenSource;
|
||||
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.StatementSource;
|
||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
import dk.camelot64.kickc.parser.*;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -22,18 +31,14 @@ public class CPreprocessor implements TokenSource {
|
||||
*/
|
||||
private Map<String, List<Token>> defines;
|
||||
|
||||
/** The token types. */
|
||||
private CPreprocessorTokens tokenTypes;
|
||||
|
||||
public CPreprocessor(TokenSource input, CPreprocessorTokens tokenTypes) {
|
||||
public CPreprocessor(TokenSource input, Map<String, List<Token>> defines) {
|
||||
if(input instanceof CTokenSource) {
|
||||
// If possible use the input directly instead of wrapping it
|
||||
this.input = (CTokenSource) input;
|
||||
} else {
|
||||
this.input = new CTokenSource(input);
|
||||
}
|
||||
this.defines = new LinkedHashMap<>();
|
||||
this.tokenTypes = tokenTypes;
|
||||
this.defines = defines;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -86,29 +91,30 @@ public class CPreprocessor implements TokenSource {
|
||||
* @return true if the input token was preprocessed (and should not be added to the output). False if the token was not a preprocessor token
|
||||
*/
|
||||
private boolean preprocess(Token inputToken, CTokenSource cTokenSource) {
|
||||
if(inputToken.getType() == tokenTypes.define) {
|
||||
if(inputToken.getType() == KickCLexer.DEFINE) {
|
||||
define(cTokenSource);
|
||||
return true;
|
||||
} else if(inputToken.getType() == tokenTypes.undef) {
|
||||
} else if(inputToken.getType() == KickCLexer.UNDEF) {
|
||||
undef(cTokenSource);
|
||||
return true;
|
||||
} else if(inputToken.getType() == tokenTypes.ifndef) {
|
||||
} else if(inputToken.getType() == KickCLexer.IFNDEF) {
|
||||
ifndef(cTokenSource);
|
||||
return true;
|
||||
} else if(inputToken.getType() == tokenTypes.ifdef) {
|
||||
} else if(inputToken.getType() == KickCLexer.IFDEF) {
|
||||
ifdef(cTokenSource);
|
||||
return true;
|
||||
} else if(inputToken.getType() == tokenTypes.ifelse) {
|
||||
} else if(inputToken.getType() == KickCLexer.IFIF) {
|
||||
ifif(cTokenSource);
|
||||
return true;
|
||||
} else if(inputToken.getType() == KickCLexer.IFELSE) {
|
||||
// #else means we must skip until #endif
|
||||
ifelse(cTokenSource);
|
||||
return true;
|
||||
} else if(inputToken.getType() == tokenTypes.endif) {
|
||||
} else if(inputToken.getType() == KickCLexer.ENDIF) {
|
||||
// Skip #endif - they have already been handled by #if / #else
|
||||
return true;
|
||||
} else if(inputToken.getType() == tokenTypes.identifier) {
|
||||
final boolean expanded = expand(inputToken, cTokenSource);
|
||||
if(expanded)
|
||||
return true;
|
||||
} else if(inputToken.getType() == KickCLexer.NAME) {
|
||||
return expand(inputToken, cTokenSource);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -162,7 +168,7 @@ public class CPreprocessor implements TokenSource {
|
||||
private void undef(CTokenSource cTokenSource) {
|
||||
// #undef a new macro - find the name
|
||||
skipWhitespace(cTokenSource);
|
||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
||||
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||
this.defines.remove(macroName);
|
||||
}
|
||||
|
||||
@ -173,13 +179,151 @@ public class CPreprocessor implements TokenSource {
|
||||
*/
|
||||
private void ifdef(CTokenSource cTokenSource) {
|
||||
skipWhitespace(cTokenSource);
|
||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
||||
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||
final boolean defined = this.defines.containsKey(macroName);
|
||||
if(!defined) {
|
||||
iffalse(cTokenSource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* #if checks if a constant condition expression is non-zero
|
||||
*
|
||||
* @param cTokenSource The token source used to get the condition
|
||||
*/
|
||||
private void ifif(CTokenSource cTokenSource) {
|
||||
// Read the condition body
|
||||
ArrayList<Token> conditionTokens = readBody(cTokenSource);
|
||||
// Evaluate any uses of the defined operator (to prevent expansion of the named macro)
|
||||
evaluateDefinedOperator(conditionTokens);
|
||||
// Expand the condition body before evaluating it
|
||||
CPreprocessor subPreprocessor = new CPreprocessor(new ListTokenSource(conditionTokens), new HashMap<>(defines));
|
||||
// Parse the expression
|
||||
KickCParser.ExprContext conditionExpr = ExprParser.parseExpression(subPreprocessor);
|
||||
// Evaluate the expression
|
||||
Long conditionValue = evaluateExpression(conditionExpr);
|
||||
if(conditionValue == null || conditionValue == 0L) {
|
||||
iffalse(cTokenSource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a constant condition expression from #if. The special defined operator must be evaluated before calling this.
|
||||
*
|
||||
* @param conditionExpr The expression
|
||||
* @return The result of the evaluation.
|
||||
*/
|
||||
private Long evaluateExpression(KickCParser.ExprContext conditionExpr) {
|
||||
KickCParserBaseVisitor<Long> conditionEvaluator = new KickCParserBaseVisitor<Long>() {
|
||||
@Override
|
||||
public Long visitExprNumber(KickCParser.ExprNumberContext ctx) {
|
||||
try {
|
||||
ConstantInteger constantInteger = NumberParser.parseIntegerLiteral(ctx.getText());
|
||||
return constantInteger.getInteger();
|
||||
} catch(NumberFormatException e) {
|
||||
throw new CompileError(e.getMessage(), new StatementSource(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long visitExprId(KickCParser.ExprIdContext ctx) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long visitExprBinary(KickCParser.ExprBinaryContext ctx) {
|
||||
Long left = this.visit(ctx.expr(0));
|
||||
Long right = this.visit(ctx.expr(1));
|
||||
String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText();
|
||||
OperatorBinary operator = (OperatorBinary) Operators.getBinary(op);
|
||||
ConstantLiteral result = operator.calculateLiteral(new ConstantInteger(left), new ConstantInteger(right));
|
||||
if(result instanceof ConstantInteger) {
|
||||
return ((ConstantInteger) result).getInteger();
|
||||
} else if(result instanceof ConstantBool) {
|
||||
return ((ConstantBool) result).getBool()?1L:0L;
|
||||
} else
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long visitExprUnary(KickCParser.ExprUnaryContext ctx) {
|
||||
Long left = this.visit(ctx.expr());
|
||||
String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText();
|
||||
OperatorUnary operator = (OperatorUnary) Operators.getUnary(op);
|
||||
ConstantLiteral result = operator.calculateLiteral(new ConstantInteger(left), null);
|
||||
if(result instanceof ConstantInteger) {
|
||||
return ((ConstantInteger) result).getInteger();
|
||||
} else if(result instanceof ConstantBool) {
|
||||
return ((ConstantBool) result).getBool()?1L:0L;
|
||||
} else
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long visitExprPar(KickCParser.ExprParContext ctx) {
|
||||
return this.visit(ctx.commaExpr());
|
||||
}
|
||||
|
||||
};
|
||||
return conditionEvaluator.visit(conditionExpr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and evaluate the special defined X operator which evaluates to 1 if a named macro if defined and 0 if it is undefined.
|
||||
* Works by replacing the defined X tokens with the resulting 0/1 value in the passed token list.
|
||||
* @param conditionTokens The token list
|
||||
*/
|
||||
private void evaluateDefinedOperator(ArrayList<Token> conditionTokens) {
|
||||
// First evaluate the special defined operators
|
||||
ListIterator<Token> tokenIt = conditionTokens.listIterator();
|
||||
while(tokenIt.hasNext()) {
|
||||
Token token = tokenIt.next();
|
||||
if(token.getType()== KickCLexer.DEFINED) {
|
||||
// Remove the token
|
||||
tokenIt.remove();
|
||||
// Read the macro name to examine - and skip any parenthesis
|
||||
token = getNextSkipWhitespace(tokenIt);
|
||||
boolean hasPar = false;
|
||||
if(token.getType()==KickCLexer.PAR_BEGIN) {
|
||||
tokenIt.remove();
|
||||
token = getNextSkipWhitespace(tokenIt);
|
||||
hasPar = true;
|
||||
}
|
||||
if(token.getType()!=KickCLexer.NAME) {
|
||||
throw new CompileError("Unexpected token. Was expecting NAME!");
|
||||
}
|
||||
tokenIt.remove();
|
||||
Token macroNameToken = token;
|
||||
String macroName = macroNameToken.getText();
|
||||
if(hasPar) {
|
||||
// Skip closing parenthesis
|
||||
token = getNextSkipWhitespace(tokenIt);
|
||||
if(token.getType()!=KickCLexer.PAR_END) {
|
||||
throw new CompileError("Unexpected token. Was expecting ')'!");
|
||||
}
|
||||
tokenIt.remove();
|
||||
}
|
||||
final boolean defined = defines.containsKey(macroName);
|
||||
CommonToken definedToken = new CommonToken(macroNameToken);
|
||||
definedToken.setType(KickCLexer.NUMBER);
|
||||
definedToken.setText(defined?"1":"0");
|
||||
tokenIt.add(definedToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next token from an iterator skipping whitespace (unless it has a newline)
|
||||
* @param tokenIt The iterator
|
||||
* @return The next non-whitespace token
|
||||
*/
|
||||
private Token getNextSkipWhitespace(ListIterator<Token> tokenIt) {
|
||||
Token token = tokenIt.next();
|
||||
while(token.getChannel()==CParser.CHANNEL_WHITESPACE && !token.getText().contains("\n"))
|
||||
token = tokenIt.next();
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* #ifdef checks if a macro is _NOT_ defined.
|
||||
*
|
||||
@ -187,16 +331,16 @@ public class CPreprocessor implements TokenSource {
|
||||
*/
|
||||
private void ifndef(CTokenSource cTokenSource) {
|
||||
skipWhitespace(cTokenSource);
|
||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
||||
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||
final boolean defined = this.defines.containsKey(macroName);
|
||||
if(defined) {
|
||||
iffalse(cTokenSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip tokens based in an #if that is false
|
||||
*
|
||||
* @param cTokenSource The token source
|
||||
*/
|
||||
private void iffalse(CTokenSource cTokenSource) {
|
||||
@ -205,14 +349,14 @@ public class CPreprocessor implements TokenSource {
|
||||
while(true) {
|
||||
final Token token = cTokenSource.nextToken();
|
||||
final int tokenType = token.getType();
|
||||
if(tokenType == tokenTypes.ifdef || tokenType == tokenTypes.ifndef) {
|
||||
if(tokenType == KickCLexer.IFDEF || tokenType == KickCLexer.IFNDEF || tokenType == KickCLexer.IFIF) {
|
||||
++nesting;
|
||||
} else if(tokenType == tokenTypes.ifelse) {
|
||||
} else if(tokenType == KickCLexer.IFELSE) {
|
||||
if(nesting == 1) {
|
||||
// We are at the outer #if - #else means we must generate output from here!
|
||||
return;
|
||||
}
|
||||
} else if(tokenType == tokenTypes.endif) {
|
||||
} else if(tokenType == KickCLexer.ENDIF) {
|
||||
if(--nesting == 0) {
|
||||
// We have passed the matching #endif - restart the output!
|
||||
return;
|
||||
@ -231,9 +375,9 @@ public class CPreprocessor implements TokenSource {
|
||||
while(true) {
|
||||
final Token token = cTokenSource.nextToken();
|
||||
final int tokenType = token.getType();
|
||||
if(tokenType == tokenTypes.ifdef || tokenType == tokenTypes.ifndef) {
|
||||
if(tokenType == KickCLexer.IFDEF || tokenType == KickCLexer.IFNDEF || tokenType == KickCLexer.IFIF) {
|
||||
++nesting;
|
||||
} else if(tokenType == tokenTypes.endif) {
|
||||
} else if(tokenType == KickCLexer.ENDIF) {
|
||||
if(--nesting == 0) {
|
||||
// We have passed the matching #endif
|
||||
return;
|
||||
@ -250,34 +394,45 @@ public class CPreprocessor implements TokenSource {
|
||||
private void define(CTokenSource cTokenSource) {
|
||||
// #define a new macro - find the name
|
||||
skipWhitespace(cTokenSource);
|
||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
||||
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||
// Examine whether the macro has parameters
|
||||
skipWhitespace(cTokenSource);
|
||||
if(cTokenSource.peekToken().getType() == tokenTypes.parBegin) {
|
||||
if(cTokenSource.peekToken().getType() == KickCLexer.PAR_BEGIN) {
|
||||
// Macro has parameters - find parameter name list
|
||||
throw new CompileError("Macros with parameters not supported!");
|
||||
}
|
||||
final ArrayList<Token> macroBody = readBody(cTokenSource);
|
||||
defines.put(macroName, macroBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a preprocessor body (eg. a macro body) until encountering a newline
|
||||
*
|
||||
* @param cTokenSource The token source to read from
|
||||
* @return The list of body tokens read
|
||||
*/
|
||||
private ArrayList<Token> readBody(CTokenSource cTokenSource) {
|
||||
// Find body by gobbling tokens until the line ends
|
||||
final ArrayList<Token> macroBody = new ArrayList<>();
|
||||
while(true) {
|
||||
final Token bodyToken = cTokenSource.nextToken();
|
||||
if(bodyToken.getType() == tokenTypes.defineMultiline) {
|
||||
if(bodyToken.getType() == KickCLexer.DEFINE_CONTINUE) {
|
||||
// Skip the multi-line token, add a newline token and continue reading body on the next line
|
||||
final CommonToken newlineToken = new CommonToken(bodyToken);
|
||||
newlineToken.setType(tokenTypes.whitespace);
|
||||
newlineToken.setChannel(tokenTypes.channelWhitespace);
|
||||
newlineToken.setType(KickCLexer.WS);
|
||||
newlineToken.setChannel(CParser.CHANNEL_WHITESPACE);
|
||||
newlineToken.setText("\n");
|
||||
macroBody.add(newlineToken);
|
||||
continue;
|
||||
}
|
||||
if(bodyToken.getChannel() == tokenTypes.channelWhitespace && bodyToken.getText().contains("\n")) {
|
||||
if(bodyToken.getChannel() == CParser.CHANNEL_WHITESPACE && bodyToken.getText().contains("\n")) {
|
||||
// Done reading the body
|
||||
break;
|
||||
} else {
|
||||
macroBody.add(bodyToken);
|
||||
}
|
||||
}
|
||||
defines.put(macroName, macroBody);
|
||||
return macroBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -302,7 +457,7 @@ public class CPreprocessor implements TokenSource {
|
||||
private void skipWhitespace(CTokenSource cTokenSource) {
|
||||
while(true) {
|
||||
final Token token = cTokenSource.peekToken();
|
||||
if(token.getChannel() != tokenTypes.channelWhitespace)
|
||||
if(token.getChannel() != CParser.CHANNEL_WHITESPACE)
|
||||
break;
|
||||
if(token.getText().contains("\n"))
|
||||
break;
|
||||
|
@ -1,50 +0,0 @@
|
||||
package dk.camelot64.kickc.preprocessor;
|
||||
|
||||
/**
|
||||
* Tokens used by the preprocessor
|
||||
*/
|
||||
public class CPreprocessorTokens {
|
||||
|
||||
/** The channel containing whitespaces. */
|
||||
final int channelWhitespace;
|
||||
/** The token type for tokens containing whitespace. */
|
||||
final int whitespace;
|
||||
/** The token type for #define. */
|
||||
final int define;
|
||||
/** The token type for define multi-line. */
|
||||
final int defineMultiline;
|
||||
/** The token type for #undef. */
|
||||
final int undef;
|
||||
/** The token type for #ifdef. */
|
||||
final int ifdef;
|
||||
/** The token type for #ifndef. */
|
||||
final int ifndef;
|
||||
/** The token type for #else. */
|
||||
final int ifelse;
|
||||
/** The token type for #endif. */
|
||||
final int endif;
|
||||
/** The token type for identifiers. */
|
||||
final int identifier;
|
||||
/** The token type for parenthesis begin. */
|
||||
final int parBegin;
|
||||
/** The token type for parenthesis end. */
|
||||
final int parEnd;
|
||||
/** The token type for comma. */
|
||||
final int comma;
|
||||
|
||||
public CPreprocessorTokens(int channelWhitespace, int whitespace, int define, int identifier, int defineMultiline, int undef, int ifdef, int ifndef, int ifelse, int endif, int parBegin, int parEnd, int comma) {
|
||||
this.channelWhitespace = channelWhitespace;
|
||||
this.whitespace = whitespace;
|
||||
this.define = define;
|
||||
this.identifier = identifier;
|
||||
this.defineMultiline = defineMultiline;
|
||||
this.undef = undef;
|
||||
this.ifdef = ifdef;
|
||||
this.ifndef = ifndef;
|
||||
this.ifelse = ifelse;
|
||||
this.endif = endif;
|
||||
this.parBegin = parBegin;
|
||||
this.parEnd = parEnd;
|
||||
this.comma = comma;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Minimal grammar implementing C macros
|
||||
*/
|
||||
|
||||
grammar Macros;
|
||||
|
||||
@header {
|
||||
}
|
||||
|
||||
@parser::members {
|
||||
}
|
||||
|
||||
@lexer::members {
|
||||
}
|
||||
|
||||
stmtSeq
|
||||
: stmt*
|
||||
;
|
||||
|
||||
stmt
|
||||
: expr ';' #stmtExpr
|
||||
;
|
||||
|
||||
expr
|
||||
: PAR_BEGIN SIMPLETYPE PAR_END expr #exprCast
|
||||
| IDENTIFIER #exprName
|
||||
| NUMBER #exprNumber
|
||||
| PAR_BEGIN expr PAR_END #exprPar
|
||||
| expr '*' expr #exprBinary
|
||||
| expr '/' expr #exprBinary
|
||||
| expr '+' expr #exprBinary
|
||||
| expr '-' expr #exprBinary
|
||||
| expr COMMA expr #exprBinary
|
||||
;
|
||||
|
||||
PAR_BEGIN: '(' ;
|
||||
PAR_END: ')' ;
|
||||
COMMA : ',' ;
|
||||
SIMPLETYPE: 'char' | 'int' ;
|
||||
IDENTIFIER: [a-zA-Z_][a-zA-Z_0-9]* ;
|
||||
NUMBER: [0-9]+ ;
|
||||
DEFINE: '#define' ;
|
||||
UNDEF: '#undef' ;
|
||||
IFDEF: '#ifdef' ;
|
||||
IFNDEF: '#ifndef' ;
|
||||
IFELSE: '#else' ;
|
||||
ENDIF: '#endif' ;
|
||||
DEFINE_CONTINUE: '\\\n' ;
|
||||
WHITESPACE: [ \t\r\n]+ -> channel(1) ; // Send whitespace to the hidden WS channel
|
@ -1,52 +0,0 @@
|
||||
token literal names:
|
||||
null
|
||||
';'
|
||||
'*'
|
||||
'/'
|
||||
'+'
|
||||
'-'
|
||||
'('
|
||||
')'
|
||||
','
|
||||
null
|
||||
null
|
||||
null
|
||||
'#define'
|
||||
'#undef'
|
||||
'#ifdef'
|
||||
'#ifndef'
|
||||
'#else'
|
||||
'#endif'
|
||||
'\\\n'
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
PAR_BEGIN
|
||||
PAR_END
|
||||
COMMA
|
||||
SIMPLETYPE
|
||||
IDENTIFIER
|
||||
NUMBER
|
||||
DEFINE
|
||||
UNDEF
|
||||
IFDEF
|
||||
IFNDEF
|
||||
IFELSE
|
||||
ENDIF
|
||||
DEFINE_CONTINUE
|
||||
WHITESPACE
|
||||
|
||||
rule names:
|
||||
stmtSeq
|
||||
stmt
|
||||
expr
|
||||
|
||||
|
||||
atn:
|
||||
[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 21, 51, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 3, 2, 7, 2, 10, 10, 2, 12, 2, 14, 2, 13, 11, 2, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 29, 10, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 7, 4, 46, 10, 4, 12, 4, 14, 4, 49, 11, 4, 3, 4, 2, 3, 6, 5, 2, 4, 6, 2, 2, 2, 56, 2, 11, 3, 2, 2, 2, 4, 14, 3, 2, 2, 2, 6, 28, 3, 2, 2, 2, 8, 10, 5, 4, 3, 2, 9, 8, 3, 2, 2, 2, 10, 13, 3, 2, 2, 2, 11, 9, 3, 2, 2, 2, 11, 12, 3, 2, 2, 2, 12, 3, 3, 2, 2, 2, 13, 11, 3, 2, 2, 2, 14, 15, 5, 6, 4, 2, 15, 16, 7, 3, 2, 2, 16, 5, 3, 2, 2, 2, 17, 18, 8, 4, 1, 2, 18, 19, 7, 8, 2, 2, 19, 20, 7, 11, 2, 2, 20, 21, 7, 9, 2, 2, 21, 29, 5, 6, 4, 11, 22, 29, 7, 12, 2, 2, 23, 29, 7, 13, 2, 2, 24, 25, 7, 8, 2, 2, 25, 26, 5, 6, 4, 2, 26, 27, 7, 9, 2, 2, 27, 29, 3, 2, 2, 2, 28, 17, 3, 2, 2, 2, 28, 22, 3, 2, 2, 2, 28, 23, 3, 2, 2, 2, 28, 24, 3, 2, 2, 2, 29, 47, 3, 2, 2, 2, 30, 31, 12, 7, 2, 2, 31, 32, 7, 4, 2, 2, 32, 46, 5, 6, 4, 8, 33, 34, 12, 6, 2, 2, 34, 35, 7, 5, 2, 2, 35, 46, 5, 6, 4, 7, 36, 37, 12, 5, 2, 2, 37, 38, 7, 6, 2, 2, 38, 46, 5, 6, 4, 6, 39, 40, 12, 4, 2, 2, 40, 41, 7, 7, 2, 2, 41, 46, 5, 6, 4, 5, 42, 43, 12, 3, 2, 2, 43, 44, 7, 10, 2, 2, 44, 46, 5, 6, 4, 4, 45, 30, 3, 2, 2, 2, 45, 33, 3, 2, 2, 2, 45, 36, 3, 2, 2, 2, 45, 39, 3, 2, 2, 2, 45, 42, 3, 2, 2, 2, 46, 49, 3, 2, 2, 2, 47, 45, 3, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 7, 3, 2, 2, 2, 49, 47, 3, 2, 2, 2, 6, 11, 28, 45, 47]
|
@ -1,34 +0,0 @@
|
||||
T__0=1
|
||||
T__1=2
|
||||
T__2=3
|
||||
T__3=4
|
||||
T__4=5
|
||||
PAR_BEGIN=6
|
||||
PAR_END=7
|
||||
COMMA=8
|
||||
SIMPLETYPE=9
|
||||
IDENTIFIER=10
|
||||
NUMBER=11
|
||||
DEFINE=12
|
||||
UNDEF=13
|
||||
IFDEF=14
|
||||
IFNDEF=15
|
||||
IFELSE=16
|
||||
ENDIF=17
|
||||
DEFINE_CONTINUE=18
|
||||
WHITESPACE=19
|
||||
';'=1
|
||||
'*'=2
|
||||
'/'=3
|
||||
'+'=4
|
||||
'-'=5
|
||||
'('=6
|
||||
')'=7
|
||||
','=8
|
||||
'#define'=12
|
||||
'#undef'=13
|
||||
'#ifdef'=14
|
||||
'#ifndef'=15
|
||||
'#else'=16
|
||||
'#endif'=17
|
||||
'\\\n'=18
|
@ -1,125 +0,0 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/macros/Macros.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link MacrosListener},
|
||||
* which can be extended to create a listener which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*/
|
||||
public class MacrosBaseListener implements MacrosListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterStmtSeq(MacrosParser.StmtSeqContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitStmtSeq(MacrosParser.StmtSeqContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterStmtExpr(MacrosParser.StmtExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitStmtExpr(MacrosParser.StmtExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprCast(MacrosParser.ExprCastContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprCast(MacrosParser.ExprCastContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprBinary(MacrosParser.ExprBinaryContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprBinary(MacrosParser.ExprBinaryContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprPar(MacrosParser.ExprParContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprPar(MacrosParser.ExprParContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprNumber(MacrosParser.ExprNumberContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprNumber(MacrosParser.ExprNumberContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprName(MacrosParser.ExprNameContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprName(MacrosParser.ExprNameContext ctx) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitTerminal(TerminalNode node) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitErrorNode(ErrorNode node) { }
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/macros/Macros.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link MacrosVisitor},
|
||||
* which can be extended to create a visitor which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
public class MacrosBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements MacrosVisitor<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitStmtSeq(MacrosParser.StmtSeqContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitStmtExpr(MacrosParser.StmtExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprCast(MacrosParser.ExprCastContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprBinary(MacrosParser.ExprBinaryContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprPar(MacrosParser.ExprParContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprNumber(MacrosParser.ExprNumberContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprName(MacrosParser.ExprNameContext ctx) { return visitChildren(ctx); }
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
token literal names:
|
||||
null
|
||||
';'
|
||||
'*'
|
||||
'/'
|
||||
'+'
|
||||
'-'
|
||||
'('
|
||||
')'
|
||||
','
|
||||
null
|
||||
null
|
||||
null
|
||||
'#define'
|
||||
'#undef'
|
||||
'#ifdef'
|
||||
'#ifndef'
|
||||
'#else'
|
||||
'#endif'
|
||||
'\\\n'
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
PAR_BEGIN
|
||||
PAR_END
|
||||
COMMA
|
||||
SIMPLETYPE
|
||||
IDENTIFIER
|
||||
NUMBER
|
||||
DEFINE
|
||||
UNDEF
|
||||
IFDEF
|
||||
IFNDEF
|
||||
IFELSE
|
||||
ENDIF
|
||||
DEFINE_CONTINUE
|
||||
WHITESPACE
|
||||
|
||||
rule names:
|
||||
T__0
|
||||
T__1
|
||||
T__2
|
||||
T__3
|
||||
T__4
|
||||
PAR_BEGIN
|
||||
PAR_END
|
||||
COMMA
|
||||
SIMPLETYPE
|
||||
IDENTIFIER
|
||||
NUMBER
|
||||
DEFINE
|
||||
UNDEF
|
||||
IFDEF
|
||||
IFNDEF
|
||||
IFELSE
|
||||
ENDIF
|
||||
DEFINE_CONTINUE
|
||||
WHITESPACE
|
||||
|
||||
channel names:
|
||||
DEFAULT_TOKEN_CHANNEL
|
||||
HIDDEN
|
||||
|
||||
mode names:
|
||||
DEFAULT_MODE
|
||||
|
||||
atn:
|
||||
[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 21, 131, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 65, 10, 10, 3, 11, 3, 11, 7, 11, 69, 10, 11, 12, 11, 14, 11, 72, 11, 11, 3, 12, 6, 12, 75, 10, 12, 13, 12, 14, 12, 76, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 20, 6, 20, 126, 10, 20, 13, 20, 14, 20, 127, 3, 20, 3, 20, 2, 2, 21, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 3, 2, 6, 5, 2, 67, 92, 97, 97, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 3, 2, 50, 59, 5, 2, 11, 12, 15, 15, 34, 34, 2, 134, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 3, 41, 3, 2, 2, 2, 5, 43, 3, 2, 2, 2, 7, 45, 3, 2, 2, 2, 9, 47, 3, 2, 2, 2, 11, 49, 3, 2, 2, 2, 13, 51, 3, 2, 2, 2, 15, 53, 3, 2, 2, 2, 17, 55, 3, 2, 2, 2, 19, 64, 3, 2, 2, 2, 21, 66, 3, 2, 2, 2, 23, 74, 3, 2, 2, 2, 25, 78, 3, 2, 2, 2, 27, 86, 3, 2, 2, 2, 29, 93, 3, 2, 2, 2, 31, 100, 3, 2, 2, 2, 33, 108, 3, 2, 2, 2, 35, 114, 3, 2, 2, 2, 37, 121, 3, 2, 2, 2, 39, 125, 3, 2, 2, 2, 41, 42, 7, 61, 2, 2, 42, 4, 3, 2, 2, 2, 43, 44, 7, 44, 2, 2, 44, 6, 3, 2, 2, 2, 45, 46, 7, 49, 2, 2, 46, 8, 3, 2, 2, 2, 47, 48, 7, 45, 2, 2, 48, 10, 3, 2, 2, 2, 49, 50, 7, 47, 2, 2, 50, 12, 3, 2, 2, 2, 51, 52, 7, 42, 2, 2, 52, 14, 3, 2, 2, 2, 53, 54, 7, 43, 2, 2, 54, 16, 3, 2, 2, 2, 55, 56, 7, 46, 2, 2, 56, 18, 3, 2, 2, 2, 57, 58, 7, 101, 2, 2, 58, 59, 7, 106, 2, 2, 59, 60, 7, 99, 2, 2, 60, 65, 7, 116, 2, 2, 61, 62, 7, 107, 2, 2, 62, 63, 7, 112, 2, 2, 63, 65, 7, 118, 2, 2, 64, 57, 3, 2, 2, 2, 64, 61, 3, 2, 2, 2, 65, 20, 3, 2, 2, 2, 66, 70, 9, 2, 2, 2, 67, 69, 9, 3, 2, 2, 68, 67, 3, 2, 2, 2, 69, 72, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, 70, 71, 3, 2, 2, 2, 71, 22, 3, 2, 2, 2, 72, 70, 3, 2, 2, 2, 73, 75, 9, 4, 2, 2, 74, 73, 3, 2, 2, 2, 75, 76, 3, 2, 2, 2, 76, 74, 3, 2, 2, 2, 76, 77, 3, 2, 2, 2, 77, 24, 3, 2, 2, 2, 78, 79, 7, 37, 2, 2, 79, 80, 7, 102, 2, 2, 80, 81, 7, 103, 2, 2, 81, 82, 7, 104, 2, 2, 82, 83, 7, 107, 2, 2, 83, 84, 7, 112, 2, 2, 84, 85, 7, 103, 2, 2, 85, 26, 3, 2, 2, 2, 86, 87, 7, 37, 2, 2, 87, 88, 7, 119, 2, 2, 88, 89, 7, 112, 2, 2, 89, 90, 7, 102, 2, 2, 90, 91, 7, 103, 2, 2, 91, 92, 7, 104, 2, 2, 92, 28, 3, 2, 2, 2, 93, 94, 7, 37, 2, 2, 94, 95, 7, 107, 2, 2, 95, 96, 7, 104, 2, 2, 96, 97, 7, 102, 2, 2, 97, 98, 7, 103, 2, 2, 98, 99, 7, 104, 2, 2, 99, 30, 3, 2, 2, 2, 100, 101, 7, 37, 2, 2, 101, 102, 7, 107, 2, 2, 102, 103, 7, 104, 2, 2, 103, 104, 7, 112, 2, 2, 104, 105, 7, 102, 2, 2, 105, 106, 7, 103, 2, 2, 106, 107, 7, 104, 2, 2, 107, 32, 3, 2, 2, 2, 108, 109, 7, 37, 2, 2, 109, 110, 7, 103, 2, 2, 110, 111, 7, 110, 2, 2, 111, 112, 7, 117, 2, 2, 112, 113, 7, 103, 2, 2, 113, 34, 3, 2, 2, 2, 114, 115, 7, 37, 2, 2, 115, 116, 7, 103, 2, 2, 116, 117, 7, 112, 2, 2, 117, 118, 7, 102, 2, 2, 118, 119, 7, 107, 2, 2, 119, 120, 7, 104, 2, 2, 120, 36, 3, 2, 2, 2, 121, 122, 7, 94, 2, 2, 122, 123, 7, 12, 2, 2, 123, 38, 3, 2, 2, 2, 124, 126, 9, 5, 2, 2, 125, 124, 3, 2, 2, 2, 126, 127, 3, 2, 2, 2, 127, 125, 3, 2, 2, 2, 127, 128, 3, 2, 2, 2, 128, 129, 3, 2, 2, 2, 129, 130, 8, 20, 2, 2, 130, 40, 3, 2, 2, 2, 7, 2, 64, 70, 76, 127, 3, 2, 3, 2]
|
@ -1,159 +0,0 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/macros/Macros.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class MacrosLexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, PAR_BEGIN=6, PAR_END=7, COMMA=8,
|
||||
SIMPLETYPE=9, IDENTIFIER=10, NUMBER=11, DEFINE=12, UNDEF=13, IFDEF=14,
|
||||
IFNDEF=15, IFELSE=16, ENDIF=17, DEFINE_CONTINUE=18, WHITESPACE=19;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
|
||||
public static String[] modeNames = {
|
||||
"DEFAULT_MODE"
|
||||
};
|
||||
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"T__0", "T__1", "T__2", "T__3", "T__4", "PAR_BEGIN", "PAR_END", "COMMA",
|
||||
"SIMPLETYPE", "IDENTIFIER", "NUMBER", "DEFINE", "UNDEF", "IFDEF", "IFNDEF",
|
||||
"IFELSE", "ENDIF", "DEFINE_CONTINUE", "WHITESPACE"
|
||||
};
|
||||
}
|
||||
public static final String[] ruleNames = makeRuleNames();
|
||||
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, "';'", "'*'", "'/'", "'+'", "'-'", "'('", "')'", "','", null, null,
|
||||
null, "'#define'", "'#undef'", "'#ifdef'", "'#ifndef'", "'#else'", "'#endif'",
|
||||
"'\\\n'"
|
||||
};
|
||||
}
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, null, null, null, null, null, "PAR_BEGIN", "PAR_END", "COMMA",
|
||||
"SIMPLETYPE", "IDENTIFIER", "NUMBER", "DEFINE", "UNDEF", "IFDEF", "IFNDEF",
|
||||
"IFELSE", "ENDIF", "DEFINE_CONTINUE", "WHITESPACE"
|
||||
};
|
||||
}
|
||||
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public MacrosLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "Macros.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public String[] getChannelNames() { return channelNames; }
|
||||
|
||||
@Override
|
||||
public String[] getModeNames() { return modeNames; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\25\u0083\b\1\4\2"+
|
||||
"\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
|
||||
"\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
|
||||
"\t\22\4\23\t\23\4\24\t\24\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7"+
|
||||
"\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\5\nA\n\n\3\13\3\13\7"+
|
||||
"\13E\n\13\f\13\16\13H\13\13\3\f\6\fK\n\f\r\f\16\fL\3\r\3\r\3\r\3\r\3\r"+
|
||||
"\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3"+
|
||||
"\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3"+
|
||||
"\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\24\6"+
|
||||
"\24~\n\24\r\24\16\24\177\3\24\3\24\2\2\25\3\3\5\4\7\5\t\6\13\7\r\b\17"+
|
||||
"\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25\3\2\6"+
|
||||
"\5\2C\\aac|\6\2\62;C\\aac|\3\2\62;\5\2\13\f\17\17\"\"\2\u0086\2\3\3\2"+
|
||||
"\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17"+
|
||||
"\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2"+
|
||||
"\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3"+
|
||||
"\2\2\2\2\'\3\2\2\2\3)\3\2\2\2\5+\3\2\2\2\7-\3\2\2\2\t/\3\2\2\2\13\61\3"+
|
||||
"\2\2\2\r\63\3\2\2\2\17\65\3\2\2\2\21\67\3\2\2\2\23@\3\2\2\2\25B\3\2\2"+
|
||||
"\2\27J\3\2\2\2\31N\3\2\2\2\33V\3\2\2\2\35]\3\2\2\2\37d\3\2\2\2!l\3\2\2"+
|
||||
"\2#r\3\2\2\2%y\3\2\2\2\'}\3\2\2\2)*\7=\2\2*\4\3\2\2\2+,\7,\2\2,\6\3\2"+
|
||||
"\2\2-.\7\61\2\2.\b\3\2\2\2/\60\7-\2\2\60\n\3\2\2\2\61\62\7/\2\2\62\f\3"+
|
||||
"\2\2\2\63\64\7*\2\2\64\16\3\2\2\2\65\66\7+\2\2\66\20\3\2\2\2\678\7.\2"+
|
||||
"\28\22\3\2\2\29:\7e\2\2:;\7j\2\2;<\7c\2\2<A\7t\2\2=>\7k\2\2>?\7p\2\2?"+
|
||||
"A\7v\2\2@9\3\2\2\2@=\3\2\2\2A\24\3\2\2\2BF\t\2\2\2CE\t\3\2\2DC\3\2\2\2"+
|
||||
"EH\3\2\2\2FD\3\2\2\2FG\3\2\2\2G\26\3\2\2\2HF\3\2\2\2IK\t\4\2\2JI\3\2\2"+
|
||||
"\2KL\3\2\2\2LJ\3\2\2\2LM\3\2\2\2M\30\3\2\2\2NO\7%\2\2OP\7f\2\2PQ\7g\2"+
|
||||
"\2QR\7h\2\2RS\7k\2\2ST\7p\2\2TU\7g\2\2U\32\3\2\2\2VW\7%\2\2WX\7w\2\2X"+
|
||||
"Y\7p\2\2YZ\7f\2\2Z[\7g\2\2[\\\7h\2\2\\\34\3\2\2\2]^\7%\2\2^_\7k\2\2_`"+
|
||||
"\7h\2\2`a\7f\2\2ab\7g\2\2bc\7h\2\2c\36\3\2\2\2de\7%\2\2ef\7k\2\2fg\7h"+
|
||||
"\2\2gh\7p\2\2hi\7f\2\2ij\7g\2\2jk\7h\2\2k \3\2\2\2lm\7%\2\2mn\7g\2\2n"+
|
||||
"o\7n\2\2op\7u\2\2pq\7g\2\2q\"\3\2\2\2rs\7%\2\2st\7g\2\2tu\7p\2\2uv\7f"+
|
||||
"\2\2vw\7k\2\2wx\7h\2\2x$\3\2\2\2yz\7^\2\2z{\7\f\2\2{&\3\2\2\2|~\t\5\2"+
|
||||
"\2}|\3\2\2\2~\177\3\2\2\2\177}\3\2\2\2\177\u0080\3\2\2\2\u0080\u0081\3"+
|
||||
"\2\2\2\u0081\u0082\b\24\2\2\u0082(\3\2\2\2\7\2@FL\177\3\2\3\2";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
T__0=1
|
||||
T__1=2
|
||||
T__2=3
|
||||
T__3=4
|
||||
T__4=5
|
||||
PAR_BEGIN=6
|
||||
PAR_END=7
|
||||
COMMA=8
|
||||
SIMPLETYPE=9
|
||||
IDENTIFIER=10
|
||||
NUMBER=11
|
||||
DEFINE=12
|
||||
UNDEF=13
|
||||
IFDEF=14
|
||||
IFNDEF=15
|
||||
IFELSE=16
|
||||
ENDIF=17
|
||||
DEFINE_CONTINUE=18
|
||||
WHITESPACE=19
|
||||
';'=1
|
||||
'*'=2
|
||||
'/'=3
|
||||
'+'=4
|
||||
'-'=5
|
||||
'('=6
|
||||
')'=7
|
||||
','=8
|
||||
'#define'=12
|
||||
'#undef'=13
|
||||
'#ifdef'=14
|
||||
'#ifndef'=15
|
||||
'#else'=16
|
||||
'#endif'=17
|
||||
'\\\n'=18
|
@ -1,94 +0,0 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/macros/Macros.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
|
||||
/**
|
||||
* This interface defines a complete listener for a parse tree produced by
|
||||
* {@link MacrosParser}.
|
||||
*/
|
||||
public interface MacrosListener extends ParseTreeListener {
|
||||
/**
|
||||
* Enter a parse tree produced by {@link MacrosParser#stmtSeq}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterStmtSeq(MacrosParser.StmtSeqContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link MacrosParser#stmtSeq}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitStmtSeq(MacrosParser.StmtSeqContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code stmtExpr}
|
||||
* labeled alternative in {@link MacrosParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterStmtExpr(MacrosParser.StmtExprContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code stmtExpr}
|
||||
* labeled alternative in {@link MacrosParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitStmtExpr(MacrosParser.StmtExprContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprCast}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprCast(MacrosParser.ExprCastContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprCast}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprCast(MacrosParser.ExprCastContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprBinary}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprBinary(MacrosParser.ExprBinaryContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprBinary}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprBinary(MacrosParser.ExprBinaryContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprPar}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprPar(MacrosParser.ExprParContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprPar}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprPar(MacrosParser.ExprParContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprNumber}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprNumber(MacrosParser.ExprNumberContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprNumber}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprNumber(MacrosParser.ExprNumberContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprName}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprName(MacrosParser.ExprNameContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprName}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprName(MacrosParser.ExprNameContext ctx);
|
||||
}
|
@ -1,533 +0,0 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/macros/Macros.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
import org.antlr.v4.runtime.tree.*;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class MacrosParser extends Parser {
|
||||
static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, PAR_BEGIN=6, PAR_END=7, COMMA=8,
|
||||
SIMPLETYPE=9, IDENTIFIER=10, NUMBER=11, DEFINE=12, UNDEF=13, IFDEF=14,
|
||||
IFNDEF=15, IFELSE=16, ENDIF=17, DEFINE_CONTINUE=18, WHITESPACE=19;
|
||||
public static final int
|
||||
RULE_stmtSeq = 0, RULE_stmt = 1, RULE_expr = 2;
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"stmtSeq", "stmt", "expr"
|
||||
};
|
||||
}
|
||||
public static final String[] ruleNames = makeRuleNames();
|
||||
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, "';'", "'*'", "'/'", "'+'", "'-'", "'('", "')'", "','", null, null,
|
||||
null, "'#define'", "'#undef'", "'#ifdef'", "'#ifndef'", "'#else'", "'#endif'",
|
||||
"'\\\n'"
|
||||
};
|
||||
}
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, null, null, null, null, null, "PAR_BEGIN", "PAR_END", "COMMA",
|
||||
"SIMPLETYPE", "IDENTIFIER", "NUMBER", "DEFINE", "UNDEF", "IFDEF", "IFNDEF",
|
||||
"IFELSE", "ENDIF", "DEFINE_CONTINUE", "WHITESPACE"
|
||||
};
|
||||
}
|
||||
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "Macros.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
|
||||
|
||||
public MacrosParser(TokenStream input) {
|
||||
super(input);
|
||||
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
public static class StmtSeqContext extends ParserRuleContext {
|
||||
public List<StmtContext> stmt() {
|
||||
return getRuleContexts(StmtContext.class);
|
||||
}
|
||||
public StmtContext stmt(int i) {
|
||||
return getRuleContext(StmtContext.class,i);
|
||||
}
|
||||
public StmtSeqContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
}
|
||||
@Override public int getRuleIndex() { return RULE_stmtSeq; }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterStmtSeq(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitStmtSeq(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitStmtSeq(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
||||
public final StmtSeqContext stmtSeq() throws RecognitionException {
|
||||
StmtSeqContext _localctx = new StmtSeqContext(_ctx, getState());
|
||||
enterRule(_localctx, 0, RULE_stmtSeq);
|
||||
int _la;
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(9);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << PAR_BEGIN) | (1L << IDENTIFIER) | (1L << NUMBER))) != 0)) {
|
||||
{
|
||||
{
|
||||
setState(6);
|
||||
stmt();
|
||||
}
|
||||
}
|
||||
setState(11);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
_localctx.exception = re;
|
||||
_errHandler.reportError(this, re);
|
||||
_errHandler.recover(this, re);
|
||||
}
|
||||
finally {
|
||||
exitRule();
|
||||
}
|
||||
return _localctx;
|
||||
}
|
||||
|
||||
public static class StmtContext extends ParserRuleContext {
|
||||
public StmtContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
}
|
||||
@Override public int getRuleIndex() { return RULE_stmt; }
|
||||
|
||||
public StmtContext() { }
|
||||
public void copyFrom(StmtContext ctx) {
|
||||
super.copyFrom(ctx);
|
||||
}
|
||||
}
|
||||
public static class StmtExprContext extends StmtContext {
|
||||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public StmtExprContext(StmtContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterStmtExpr(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitStmtExpr(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitStmtExpr(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
||||
public final StmtContext stmt() throws RecognitionException {
|
||||
StmtContext _localctx = new StmtContext(_ctx, getState());
|
||||
enterRule(_localctx, 2, RULE_stmt);
|
||||
try {
|
||||
_localctx = new StmtExprContext(_localctx);
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(12);
|
||||
expr(0);
|
||||
setState(13);
|
||||
match(T__0);
|
||||
}
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
_localctx.exception = re;
|
||||
_errHandler.reportError(this, re);
|
||||
_errHandler.recover(this, re);
|
||||
}
|
||||
finally {
|
||||
exitRule();
|
||||
}
|
||||
return _localctx;
|
||||
}
|
||||
|
||||
public static class ExprContext extends ParserRuleContext {
|
||||
public ExprContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
}
|
||||
@Override public int getRuleIndex() { return RULE_expr; }
|
||||
|
||||
public ExprContext() { }
|
||||
public void copyFrom(ExprContext ctx) {
|
||||
super.copyFrom(ctx);
|
||||
}
|
||||
}
|
||||
public static class ExprCastContext extends ExprContext {
|
||||
public TerminalNode PAR_BEGIN() { return getToken(MacrosParser.PAR_BEGIN, 0); }
|
||||
public TerminalNode SIMPLETYPE() { return getToken(MacrosParser.SIMPLETYPE, 0); }
|
||||
public TerminalNode PAR_END() { return getToken(MacrosParser.PAR_END, 0); }
|
||||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public ExprCastContext(ExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterExprCast(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitExprCast(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitExprCast(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class ExprBinaryContext extends ExprContext {
|
||||
public List<ExprContext> expr() {
|
||||
return getRuleContexts(ExprContext.class);
|
||||
}
|
||||
public ExprContext expr(int i) {
|
||||
return getRuleContext(ExprContext.class,i);
|
||||
}
|
||||
public TerminalNode COMMA() { return getToken(MacrosParser.COMMA, 0); }
|
||||
public ExprBinaryContext(ExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterExprBinary(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitExprBinary(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitExprBinary(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class ExprParContext extends ExprContext {
|
||||
public TerminalNode PAR_BEGIN() { return getToken(MacrosParser.PAR_BEGIN, 0); }
|
||||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public TerminalNode PAR_END() { return getToken(MacrosParser.PAR_END, 0); }
|
||||
public ExprParContext(ExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterExprPar(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitExprPar(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitExprPar(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class ExprNumberContext extends ExprContext {
|
||||
public TerminalNode NUMBER() { return getToken(MacrosParser.NUMBER, 0); }
|
||||
public ExprNumberContext(ExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterExprNumber(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitExprNumber(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitExprNumber(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class ExprNameContext extends ExprContext {
|
||||
public TerminalNode IDENTIFIER() { return getToken(MacrosParser.IDENTIFIER, 0); }
|
||||
public ExprNameContext(ExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).enterExprName(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof MacrosListener ) ((MacrosListener)listener).exitExprName(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof MacrosVisitor ) return ((MacrosVisitor<? extends T>)visitor).visitExprName(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
||||
public final ExprContext expr() throws RecognitionException {
|
||||
return expr(0);
|
||||
}
|
||||
|
||||
private ExprContext expr(int _p) throws RecognitionException {
|
||||
ParserRuleContext _parentctx = _ctx;
|
||||
int _parentState = getState();
|
||||
ExprContext _localctx = new ExprContext(_ctx, _parentState);
|
||||
ExprContext _prevctx = _localctx;
|
||||
int _startState = 4;
|
||||
enterRecursionRule(_localctx, 4, RULE_expr, _p);
|
||||
try {
|
||||
int _alt;
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(26);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new ExprCastContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
|
||||
setState(16);
|
||||
match(PAR_BEGIN);
|
||||
setState(17);
|
||||
match(SIMPLETYPE);
|
||||
setState(18);
|
||||
match(PAR_END);
|
||||
setState(19);
|
||||
expr(9);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
_localctx = new ExprNameContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(20);
|
||||
match(IDENTIFIER);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
_localctx = new ExprNumberContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(21);
|
||||
match(NUMBER);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
_localctx = new ExprParContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(22);
|
||||
match(PAR_BEGIN);
|
||||
setState(23);
|
||||
expr(0);
|
||||
setState(24);
|
||||
match(PAR_END);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ctx.stop = _input.LT(-1);
|
||||
setState(45);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,3,_ctx);
|
||||
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
|
||||
if ( _alt==1 ) {
|
||||
if ( _parseListeners!=null ) triggerExitRuleEvent();
|
||||
_prevctx = _localctx;
|
||||
{
|
||||
setState(43);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(28);
|
||||
if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
|
||||
setState(29);
|
||||
match(T__1);
|
||||
setState(30);
|
||||
expr(6);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(31);
|
||||
if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)");
|
||||
setState(32);
|
||||
match(T__2);
|
||||
setState(33);
|
||||
expr(5);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(34);
|
||||
if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
|
||||
setState(35);
|
||||
match(T__3);
|
||||
setState(36);
|
||||
expr(4);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(37);
|
||||
if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
|
||||
setState(38);
|
||||
match(T__4);
|
||||
setState(39);
|
||||
expr(3);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(40);
|
||||
if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
|
||||
setState(41);
|
||||
match(COMMA);
|
||||
setState(42);
|
||||
expr(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(47);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,3,_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
_localctx.exception = re;
|
||||
_errHandler.reportError(this, re);
|
||||
_errHandler.recover(this, re);
|
||||
}
|
||||
finally {
|
||||
unrollRecursionContexts(_parentctx);
|
||||
}
|
||||
return _localctx;
|
||||
}
|
||||
|
||||
public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
|
||||
switch (ruleIndex) {
|
||||
case 2:
|
||||
return expr_sempred((ExprContext)_localctx, predIndex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private boolean expr_sempred(ExprContext _localctx, int predIndex) {
|
||||
switch (predIndex) {
|
||||
case 0:
|
||||
return precpred(_ctx, 5);
|
||||
case 1:
|
||||
return precpred(_ctx, 4);
|
||||
case 2:
|
||||
return precpred(_ctx, 3);
|
||||
case 3:
|
||||
return precpred(_ctx, 2);
|
||||
case 4:
|
||||
return precpred(_ctx, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\25\63\4\2\t\2\4\3"+
|
||||
"\t\3\4\4\t\4\3\2\7\2\n\n\2\f\2\16\2\r\13\2\3\3\3\3\3\3\3\4\3\4\3\4\3\4"+
|
||||
"\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4\35\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+
|
||||
"\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\7\4.\n\4\f\4\16\4\61\13\4\3\4\2\3\6\5\2"+
|
||||
"\4\6\2\2\28\2\13\3\2\2\2\4\16\3\2\2\2\6\34\3\2\2\2\b\n\5\4\3\2\t\b\3\2"+
|
||||
"\2\2\n\r\3\2\2\2\13\t\3\2\2\2\13\f\3\2\2\2\f\3\3\2\2\2\r\13\3\2\2\2\16"+
|
||||
"\17\5\6\4\2\17\20\7\3\2\2\20\5\3\2\2\2\21\22\b\4\1\2\22\23\7\b\2\2\23"+
|
||||
"\24\7\13\2\2\24\25\7\t\2\2\25\35\5\6\4\13\26\35\7\f\2\2\27\35\7\r\2\2"+
|
||||
"\30\31\7\b\2\2\31\32\5\6\4\2\32\33\7\t\2\2\33\35\3\2\2\2\34\21\3\2\2\2"+
|
||||
"\34\26\3\2\2\2\34\27\3\2\2\2\34\30\3\2\2\2\35/\3\2\2\2\36\37\f\7\2\2\37"+
|
||||
" \7\4\2\2 .\5\6\4\b!\"\f\6\2\2\"#\7\5\2\2#.\5\6\4\7$%\f\5\2\2%&\7\6\2"+
|
||||
"\2&.\5\6\4\6\'(\f\4\2\2()\7\7\2\2).\5\6\4\5*+\f\3\2\2+,\7\n\2\2,.\5\6"+
|
||||
"\4\4-\36\3\2\2\2-!\3\2\2\2-$\3\2\2\2-\'\3\2\2\2-*\3\2\2\2.\61\3\2\2\2"+
|
||||
"/-\3\2\2\2/\60\3\2\2\2\60\7\3\2\2\2\61/\3\2\2\2\6\13\34-/";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/macros/Macros.g4 by ANTLR 4.7.2
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
|
||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This interface defines a complete generic visitor for a parse tree produced
|
||||
* by {@link MacrosParser}.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
public interface MacrosVisitor<T> extends ParseTreeVisitor<T> {
|
||||
/**
|
||||
* Visit a parse tree produced by {@link MacrosParser#stmtSeq}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitStmtSeq(MacrosParser.StmtSeqContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code stmtExpr}
|
||||
* labeled alternative in {@link MacrosParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitStmtExpr(MacrosParser.StmtExprContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprCast}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprCast(MacrosParser.ExprCastContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprBinary}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprBinary(MacrosParser.ExprBinaryContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprPar}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprPar(MacrosParser.ExprParContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprNumber}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprNumber(MacrosParser.ExprNumberContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprName}
|
||||
* labeled alternative in {@link MacrosParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprName(MacrosParser.ExprNameContext ctx);
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
package dk.camelot64.kickc.parsing.macros;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.preprocessor.CPreprocessor;
|
||||
import dk.camelot64.kickc.preprocessor.CPreprocessorTokens;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import dk.camelot64.kickc.parser.CParser;
|
||||
import dk.camelot64.kickc.parser.KickCParser;
|
||||
import dk.camelot64.kickc.parser.KickCParserBaseVisitor;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CodePointCharStream;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TestMacrosParser {
|
||||
|
||||
private int CHANNEL_WHITESPACE = 1;
|
||||
/**
|
||||
* Test the C preprocessor
|
||||
*/
|
||||
public class TestPreprocessor {
|
||||
|
||||
/**
|
||||
* Test some parsing without macros
|
||||
@ -36,6 +38,8 @@ public class TestMacrosParser {
|
||||
public void testSimpleDefine() {
|
||||
// A simple unused define
|
||||
assertEquals("+(name:b,num:1);*(name:c,num:2);", parse("#define A a\nb+1;\nc*2;\n"));
|
||||
// A minimal used define
|
||||
assertEquals("name:a;", parse("#define A a\nA;"));
|
||||
// A simple used define
|
||||
assertEquals("+(*(name:axe,num:2),name:axe);", parse("#define A axe\nA*2+A;"));
|
||||
// A define using a special token class
|
||||
@ -116,6 +120,47 @@ public class TestMacrosParser {
|
||||
assertEquals("name:x2;name:y;", parse("#define A a\n#ifndef A\nx1;\n#else\nx2;\n#endif\ny;"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test #if
|
||||
*/
|
||||
@Test
|
||||
public void testIf() {
|
||||
// Output not generated by #if
|
||||
assertEquals("name:y;", parse("#if 0\nx;\n#endif\ny;"));
|
||||
// Output generated by #if
|
||||
assertEquals("name:x;name:y;", parse("#define A 7\n#if 7\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using a sub-define
|
||||
assertEquals("name:x;name:y;", parse("#define A 7\n#if A\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using an undefined symbol
|
||||
assertEquals("name:y;", parse("#if A\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using an symbol==0
|
||||
assertEquals("name:y;", parse("#define A 0\n#if A\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using an expression
|
||||
assertEquals("name:x;name:y;", parse("#define A 7\n#if A==7\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using an expression
|
||||
assertEquals("name:y;", parse("#define A 7\n#if A==6\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using an expression
|
||||
assertEquals("name:x;name:y;", parse("#define A 7\n#define B 8\n#if A<B\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using an expression
|
||||
assertEquals("name:y;", parse("#define A 7\n#define B 8\n#if A>B\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using an expression with a parenthesis
|
||||
assertEquals("name:x;name:y;", parse("#define A 7\n#define B 8\n#if (A<B)\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using an expression with a few parenthesis
|
||||
assertEquals("name:x;name:y;", parse("#define A 7\n#define B 8\n#if ((A)<(B))\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using an expression with a few parenthesis
|
||||
assertEquals("name:y;", parse("#define A 7\n#define B 8\n#if ((A)>(B))\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using a unary expression
|
||||
assertEquals("name:x;name:y;", parse("#define A -10\n#define B 8\n#if A<-B\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using a unary expression
|
||||
assertEquals("name:y;", parse("#define A 7\n#define B 8\n#if !(A<B)\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using an expression with an undefined symbol
|
||||
assertEquals("name:y;", parse("#define A 7\n#if A<B\nx;\n#endif\ny;"));
|
||||
// Output generated by #if using defined operator
|
||||
assertEquals("name:x;name:y;", parse("#define A X\n#if defined A\nx;\n#endif\ny;"));
|
||||
// Output not generated by #if using defined operator
|
||||
assertEquals("name:y;", parse("#if defined A\nx;\n#endif\ny;"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test define with parameters
|
||||
*/
|
||||
@ -132,55 +177,27 @@ public class TestMacrosParser {
|
||||
* @return The parse-tree in string form
|
||||
*/
|
||||
private String parse(String program) {
|
||||
final CharStream fileStream = CharStreams.fromString(program);
|
||||
// typedefs shared between lexer and parser
|
||||
MacrosLexer lexer = new MacrosLexer(fileStream);
|
||||
lexer.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
public void syntaxError(
|
||||
Recognizer<?, ?> recognizer,
|
||||
Object offendingSymbol,
|
||||
int line,
|
||||
int charPositionInLine,
|
||||
String msg,
|
||||
RecognitionException e) {
|
||||
throw new CompileError("Error parsing file " + fileStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
}
|
||||
});
|
||||
|
||||
final CPreprocessorTokens preprocessorTokens = new CPreprocessorTokens(CHANNEL_WHITESPACE, MacrosLexer.WHITESPACE, MacrosLexer.DEFINE, MacrosLexer.IDENTIFIER, MacrosLexer.DEFINE_CONTINUE, MacrosLexer.UNDEF, MacrosLexer.IFDEF, MacrosLexer.IFNDEF, MacrosLexer.IFELSE, MacrosLexer.ENDIF, MacrosLexer.PAR_BEGIN, MacrosLexer.PAR_END, MacrosLexer.COMMA);
|
||||
final CPreprocessor expandedTokenSource = new CPreprocessor(lexer, preprocessorTokens);
|
||||
MacrosParser parser = new MacrosParser(new CommonTokenStream(expandedTokenSource));
|
||||
parser.setBuildParseTree(true);
|
||||
parser.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
public void syntaxError(
|
||||
Recognizer<?, ?> recognizer,
|
||||
Object offendingSymbol,
|
||||
int line,
|
||||
int charPositionInLine,
|
||||
String msg,
|
||||
RecognitionException e) {
|
||||
throw new CompileError("Error parsing file " + fileStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
}
|
||||
});
|
||||
|
||||
CodePointCharStream charStream = CharStreams.fromString(program);
|
||||
CParser cParser = new CParser(null);
|
||||
cParser.addSource(charStream);
|
||||
KickCParser.StmtSeqContext stmtSeqContext = cParser.getParser().stmtSeq();
|
||||
MacrosPrinter printVisitor = new MacrosPrinter();
|
||||
printVisitor.visit(parser.stmtSeq());
|
||||
printVisitor.visit(stmtSeqContext);
|
||||
return printVisitor.getOut().toString();
|
||||
}
|
||||
|
||||
private static class MacrosPrinter extends MacrosBaseVisitor<Object> {
|
||||
private static class MacrosPrinter extends KickCParserBaseVisitor<Object> {
|
||||
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
public StringBuilder getOut() {
|
||||
StringBuilder getOut() {
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visitStmtSeq(MacrosParser.StmtSeqContext ctx) {
|
||||
for(MacrosParser.StmtContext stmtContext : ctx.stmt()) {
|
||||
public Object visitStmtSeq(KickCParser.StmtSeqContext ctx) {
|
||||
for(KickCParser.StmtContext stmtContext : ctx.stmt()) {
|
||||
this.visit(stmtContext);
|
||||
out.append(";");
|
||||
}
|
||||
@ -188,26 +205,20 @@ public class TestMacrosParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitStmtExpr(MacrosParser.StmtExprContext ctx) {
|
||||
this.visit(ctx.expr());
|
||||
public Object visitExprId(KickCParser.ExprIdContext ctx) {
|
||||
out.append("name:").append(ctx.NAME().getText());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExprName(MacrosParser.ExprNameContext ctx) {
|
||||
out.append("name:").append(ctx.getText());
|
||||
return null;
|
||||
public Object visitExprNumber(KickCParser.ExprNumberContext ctx) {
|
||||
return out.append("num:").append(ctx.NUMBER().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExprNumber(MacrosParser.ExprNumberContext ctx) {
|
||||
return out.append("num:").append(ctx.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExprCast(MacrosParser.ExprCastContext ctx) {
|
||||
public Object visitExprCast(KickCParser.ExprCastContext ctx) {
|
||||
out.append("cast(");
|
||||
out.append(ctx.SIMPLETYPE().getText());
|
||||
out.append(ctx.typeSpecifier().getText());
|
||||
out.append(",");
|
||||
this.visit(ctx.expr());
|
||||
out.append(")");
|
||||
@ -215,7 +226,7 @@ public class TestMacrosParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExprBinary(MacrosParser.ExprBinaryContext ctx) {
|
||||
public Object visitExprBinary(KickCParser.ExprBinaryContext ctx) {
|
||||
String fct = ctx.getChild(1).getText();
|
||||
out.append(fct).append("(");
|
||||
this.visit(ctx.expr(0));
|
||||
@ -225,11 +236,10 @@ public class TestMacrosParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visitExprPar(MacrosParser.ExprParContext ctx) {
|
||||
public Object visitExprPar(KickCParser.ExprParContext ctx) {
|
||||
out.append("(");
|
||||
this.visit(ctx.expr());
|
||||
this.visit(ctx.commaExpr());
|
||||
out.append(")");
|
||||
return null;
|
||||
}
|
Loading…
Reference in New Issue
Block a user