mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +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.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantEnumerable;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Unary Logic Not operator (!b) */
|
/** Unary Logic Not operator (!b) */
|
||||||
@ -15,6 +16,9 @@ public class OperatorLogicNot extends OperatorUnary {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral left, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral left, ProgramScope scope) {
|
||||||
|
if(left instanceof ConstantEnumerable) {
|
||||||
|
left = new ConstantBool(((ConstantEnumerable) left).getInteger()!=0);
|
||||||
|
}
|
||||||
if(left instanceof ConstantBool) {
|
if(left instanceof ConstantBool) {
|
||||||
return new ConstantBool(!((ConstantBool) left).getBool() );
|
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.preprocessor.CPreprocessor;
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.preprocessor.CPreprocessorTokens;
|
|
||||||
import org.antlr.v4.runtime.*;
|
import org.antlr.v4.runtime.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parser for C-language files.
|
* Parser for C-language files.
|
||||||
@ -65,8 +61,7 @@ public class CParser {
|
|||||||
this.program = program;
|
this.program = program;
|
||||||
this.cFiles = new LinkedHashMap<>();
|
this.cFiles = new LinkedHashMap<>();
|
||||||
this.cTokenSource = new CTokenSource();
|
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, new HashMap<>());
|
||||||
final CPreprocessor preprocessor = new CPreprocessor(cTokenSource, preprocessorTokens);
|
|
||||||
this.tokenStream = new CommonTokenStream(preprocessor);
|
this.tokenStream = new CommonTokenStream(preprocessor);
|
||||||
this.parser = new KickCParser(tokenStream, this);
|
this.parser = new KickCParser(tokenStream, this);
|
||||||
this.typedefs = new ArrayList<>();
|
this.typedefs = new ArrayList<>();
|
||||||
@ -115,6 +110,14 @@ public class CParser {
|
|||||||
return this.parser.file();
|
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
|
* Get the path of the folder containing the source file for a token
|
||||||
*
|
*
|
||||||
@ -179,25 +182,35 @@ public class CParser {
|
|||||||
program.getLog().append("PARSING " + file.getPath().replace("\\", "/"));
|
program.getLog().append("PARSING " + file.getPath().replace("\\", "/"));
|
||||||
program.getLog().append(fileStream.toString());
|
program.getLog().append(fileStream.toString());
|
||||||
}
|
}
|
||||||
KickCLexer lexer = new KickCLexer(fileStream, this);
|
KickCLexer lexer = addSource(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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
CFile cFile = new CFile(file, lexer);
|
CFile cFile = new CFile(file, lexer);
|
||||||
cFiles.put(file.getAbsolutePath(), cFile);
|
cFiles.put(file.getAbsolutePath(), cFile);
|
||||||
cTokenSource.addSource(lexer);
|
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
throw new CompileError("Error parsing file " + fileName, 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(
|
||||||
|
Recognizer<?, ?> recognizer,
|
||||||
|
Object offendingSymbol,
|
||||||
|
int line,
|
||||||
|
int charPositionInLine,
|
||||||
|
String msg,
|
||||||
|
RecognitionException e) {
|
||||||
|
throw new CompileError("Error parsing file " + charStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cTokenSource.addSource(lexer);
|
||||||
|
return lexer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ STRUCT : 'struct' ;
|
|||||||
ENUM : 'enum' ;
|
ENUM : 'enum' ;
|
||||||
SIZEOF : 'sizeof' ;
|
SIZEOF : 'sizeof' ;
|
||||||
TYPEID : 'typeid' ;
|
TYPEID : 'typeid' ;
|
||||||
|
DEFINED : 'defined' ;
|
||||||
KICKASM : 'kickasm' ;
|
KICKASM : 'kickasm' ;
|
||||||
RESOURCE : 'resource' ;
|
RESOURCE : 'resource' ;
|
||||||
USES : 'uses' ;
|
USES : 'uses' ;
|
||||||
@ -124,10 +125,12 @@ CHAR : '\'' ('\\'['"rfn] | ~'\'' ) '\'';
|
|||||||
|
|
||||||
// Macros
|
// Macros
|
||||||
DEFINE: '#define' ;
|
DEFINE: '#define' ;
|
||||||
DEFINE_CONTINUE: '\\\n' ;
|
DEFINE_CONTINUE: '\\\n' | '\\\r\n';
|
||||||
UNDEF: '#undef' ;
|
UNDEF: '#undef' ;
|
||||||
IFDEF: '#ifdef' ;
|
IFDEF: '#ifdef' ;
|
||||||
IFNDEF: '#ifndef' ;
|
IFNDEF: '#ifndef' ;
|
||||||
|
IFIF: '#if' ;
|
||||||
|
ELIF: '#elif' ;
|
||||||
IFELSE: '#else' ;
|
IFELSE: '#else' ;
|
||||||
ENDIF: '#endif' ;
|
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
|
ENUM=79
|
||||||
SIZEOF=80
|
SIZEOF=80
|
||||||
TYPEID=81
|
TYPEID=81
|
||||||
KICKASM=82
|
DEFINED=82
|
||||||
RESOURCE=83
|
KICKASM=83
|
||||||
USES=84
|
RESOURCE=84
|
||||||
CLOBBERS=85
|
USES=85
|
||||||
BYTES=86
|
CLOBBERS=86
|
||||||
CYCLES=87
|
BYTES=87
|
||||||
LOGIC_NOT=88
|
CYCLES=88
|
||||||
SIGNEDNESS=89
|
LOGIC_NOT=89
|
||||||
SIMPLETYPE=90
|
SIGNEDNESS=90
|
||||||
BOOLEAN=91
|
SIMPLETYPE=91
|
||||||
KICKASM_BODY=92
|
BOOLEAN=92
|
||||||
STRING=93
|
KICKASM_BODY=93
|
||||||
CHAR=94
|
STRING=94
|
||||||
DEFINE=95
|
CHAR=95
|
||||||
DEFINE_CONTINUE=96
|
DEFINE=96
|
||||||
UNDEF=97
|
DEFINE_CONTINUE=97
|
||||||
IFDEF=98
|
UNDEF=98
|
||||||
IFNDEF=99
|
IFDEF=99
|
||||||
IFELSE=100
|
IFNDEF=100
|
||||||
ENDIF=101
|
IFIF=101
|
||||||
NUMBER=102
|
ELIF=102
|
||||||
NUMFLOAT=103
|
IFELSE=103
|
||||||
BINFLOAT=104
|
ENDIF=104
|
||||||
DECFLOAT=105
|
NUMBER=105
|
||||||
HEXFLOAT=106
|
NUMFLOAT=106
|
||||||
NUMINT=107
|
BINFLOAT=107
|
||||||
BININTEGER=108
|
DECFLOAT=108
|
||||||
DECINTEGER=109
|
HEXFLOAT=109
|
||||||
HEXINTEGER=110
|
NUMINT=110
|
||||||
NAME=111
|
BININTEGER=111
|
||||||
WS=112
|
DECINTEGER=112
|
||||||
COMMENT_LINE=113
|
HEXINTEGER=113
|
||||||
COMMENT_BLOCK=114
|
NAME=114
|
||||||
ASM_BYTE=115
|
WS=115
|
||||||
ASM_MNEMONIC=116
|
COMMENT_LINE=116
|
||||||
ASM_IMM=117
|
COMMENT_BLOCK=117
|
||||||
ASM_COLON=118
|
ASM_BYTE=118
|
||||||
ASM_COMMA=119
|
ASM_MNEMONIC=119
|
||||||
ASM_PAR_BEGIN=120
|
ASM_IMM=120
|
||||||
ASM_PAR_END=121
|
ASM_COLON=121
|
||||||
ASM_BRACKET_BEGIN=122
|
ASM_COMMA=122
|
||||||
ASM_BRACKET_END=123
|
ASM_PAR_BEGIN=123
|
||||||
ASM_DOT=124
|
ASM_PAR_END=124
|
||||||
ASM_SHIFT_LEFT=125
|
ASM_BRACKET_BEGIN=125
|
||||||
ASM_SHIFT_RIGHT=126
|
ASM_BRACKET_END=126
|
||||||
ASM_PLUS=127
|
ASM_DOT=127
|
||||||
ASM_MINUS=128
|
ASM_SHIFT_LEFT=128
|
||||||
ASM_LESS_THAN=129
|
ASM_SHIFT_RIGHT=129
|
||||||
ASM_GREATER_THAN=130
|
ASM_PLUS=130
|
||||||
ASM_MULTIPLY=131
|
ASM_MINUS=131
|
||||||
ASM_DIVIDE=132
|
ASM_LESS_THAN=132
|
||||||
ASM_CURLY_BEGIN=133
|
ASM_GREATER_THAN=133
|
||||||
ASM_CURLY_END=134
|
ASM_MULTIPLY=134
|
||||||
ASM_NUMBER=135
|
ASM_DIVIDE=135
|
||||||
ASM_NUMFLOAT=136
|
ASM_CURLY_BEGIN=136
|
||||||
ASM_BINFLOAT=137
|
ASM_CURLY_END=137
|
||||||
ASM_DECFLOAT=138
|
ASM_NUMBER=138
|
||||||
ASM_HEXFLOAT=139
|
ASM_NUMFLOAT=139
|
||||||
ASM_NUMINT=140
|
ASM_BINFLOAT=140
|
||||||
ASM_BININTEGER=141
|
ASM_DECFLOAT=141
|
||||||
ASM_DECINTEGER=142
|
ASM_HEXFLOAT=142
|
||||||
ASM_HEXINTEGER=143
|
ASM_NUMINT=143
|
||||||
ASM_CHAR=144
|
ASM_BININTEGER=144
|
||||||
ASM_MULTI_REL=145
|
ASM_DECINTEGER=145
|
||||||
ASM_MULTI_NAME=146
|
ASM_HEXINTEGER=146
|
||||||
ASM_NAME=147
|
ASM_CHAR=147
|
||||||
ASM_WS=148
|
ASM_MULTI_REL=148
|
||||||
ASM_COMMENT_LINE=149
|
ASM_MULTI_NAME=149
|
||||||
ASM_COMMENT_BLOCK=150
|
ASM_NAME=150
|
||||||
|
ASM_WS=151
|
||||||
|
ASM_COMMENT_LINE=152
|
||||||
|
ASM_COMMENT_BLOCK=153
|
||||||
';'=8
|
';'=8
|
||||||
'..'=11
|
'..'=11
|
||||||
'?'=12
|
'?'=12
|
||||||
@ -209,19 +212,21 @@ ASM_COMMENT_BLOCK=150
|
|||||||
'enum'=79
|
'enum'=79
|
||||||
'sizeof'=80
|
'sizeof'=80
|
||||||
'typeid'=81
|
'typeid'=81
|
||||||
'kickasm'=82
|
'defined'=82
|
||||||
'resource'=83
|
'kickasm'=83
|
||||||
'uses'=84
|
'resource'=84
|
||||||
'clobbers'=85
|
'uses'=85
|
||||||
'bytes'=86
|
'clobbers'=86
|
||||||
'cycles'=87
|
'bytes'=87
|
||||||
'!'=88
|
'cycles'=88
|
||||||
'#define'=95
|
'!'=89
|
||||||
'\\\n'=96
|
'#define'=96
|
||||||
'#undef'=97
|
'#undef'=98
|
||||||
'#ifdef'=98
|
'#ifdef'=99
|
||||||
'#ifndef'=99
|
'#ifndef'=100
|
||||||
'#else'=100
|
'#if'=101
|
||||||
'#endif'=101
|
'#elif'=102
|
||||||
'.byte'=115
|
'#else'=103
|
||||||
'#'=117
|
'#endif'=104
|
||||||
|
'.byte'=118
|
||||||
|
'#'=120
|
||||||
|
@ -220,6 +220,7 @@ expr
|
|||||||
| expr PAR_BEGIN parameterList? PAR_END #exprCall
|
| expr PAR_BEGIN parameterList? PAR_END #exprCall
|
||||||
| SIZEOF PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprSizeOf
|
| SIZEOF PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprSizeOf
|
||||||
| TYPEID PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprTypeId
|
| TYPEID PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprTypeId
|
||||||
|
| DEFINED PAR_BEGIN? NAME PAR_END? #exprDefined
|
||||||
| expr BRACKET_BEGIN commaExpr BRACKET_END #exprArray
|
| expr BRACKET_BEGIN commaExpr BRACKET_END #exprArray
|
||||||
| PAR_BEGIN typeSpecifier PAR_END expr #exprCast
|
| PAR_BEGIN typeSpecifier PAR_END expr #exprCast
|
||||||
| ('--' | '++' ) expr #exprPreMod
|
| ('--' | '++' ) 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
|
ENUM=79
|
||||||
SIZEOF=80
|
SIZEOF=80
|
||||||
TYPEID=81
|
TYPEID=81
|
||||||
KICKASM=82
|
DEFINED=82
|
||||||
RESOURCE=83
|
KICKASM=83
|
||||||
USES=84
|
RESOURCE=84
|
||||||
CLOBBERS=85
|
USES=85
|
||||||
BYTES=86
|
CLOBBERS=86
|
||||||
CYCLES=87
|
BYTES=87
|
||||||
LOGIC_NOT=88
|
CYCLES=88
|
||||||
SIGNEDNESS=89
|
LOGIC_NOT=89
|
||||||
SIMPLETYPE=90
|
SIGNEDNESS=90
|
||||||
BOOLEAN=91
|
SIMPLETYPE=91
|
||||||
KICKASM_BODY=92
|
BOOLEAN=92
|
||||||
STRING=93
|
KICKASM_BODY=93
|
||||||
CHAR=94
|
STRING=94
|
||||||
DEFINE=95
|
CHAR=95
|
||||||
DEFINE_CONTINUE=96
|
DEFINE=96
|
||||||
UNDEF=97
|
DEFINE_CONTINUE=97
|
||||||
IFDEF=98
|
UNDEF=98
|
||||||
IFNDEF=99
|
IFDEF=99
|
||||||
IFELSE=100
|
IFNDEF=100
|
||||||
ENDIF=101
|
IFIF=101
|
||||||
NUMBER=102
|
ELIF=102
|
||||||
NUMFLOAT=103
|
IFELSE=103
|
||||||
BINFLOAT=104
|
ENDIF=104
|
||||||
DECFLOAT=105
|
NUMBER=105
|
||||||
HEXFLOAT=106
|
NUMFLOAT=106
|
||||||
NUMINT=107
|
BINFLOAT=107
|
||||||
BININTEGER=108
|
DECFLOAT=108
|
||||||
DECINTEGER=109
|
HEXFLOAT=109
|
||||||
HEXINTEGER=110
|
NUMINT=110
|
||||||
NAME=111
|
BININTEGER=111
|
||||||
WS=112
|
DECINTEGER=112
|
||||||
COMMENT_LINE=113
|
HEXINTEGER=113
|
||||||
COMMENT_BLOCK=114
|
NAME=114
|
||||||
ASM_BYTE=115
|
WS=115
|
||||||
ASM_MNEMONIC=116
|
COMMENT_LINE=116
|
||||||
ASM_IMM=117
|
COMMENT_BLOCK=117
|
||||||
ASM_COLON=118
|
ASM_BYTE=118
|
||||||
ASM_COMMA=119
|
ASM_MNEMONIC=119
|
||||||
ASM_PAR_BEGIN=120
|
ASM_IMM=120
|
||||||
ASM_PAR_END=121
|
ASM_COLON=121
|
||||||
ASM_BRACKET_BEGIN=122
|
ASM_COMMA=122
|
||||||
ASM_BRACKET_END=123
|
ASM_PAR_BEGIN=123
|
||||||
ASM_DOT=124
|
ASM_PAR_END=124
|
||||||
ASM_SHIFT_LEFT=125
|
ASM_BRACKET_BEGIN=125
|
||||||
ASM_SHIFT_RIGHT=126
|
ASM_BRACKET_END=126
|
||||||
ASM_PLUS=127
|
ASM_DOT=127
|
||||||
ASM_MINUS=128
|
ASM_SHIFT_LEFT=128
|
||||||
ASM_LESS_THAN=129
|
ASM_SHIFT_RIGHT=129
|
||||||
ASM_GREATER_THAN=130
|
ASM_PLUS=130
|
||||||
ASM_MULTIPLY=131
|
ASM_MINUS=131
|
||||||
ASM_DIVIDE=132
|
ASM_LESS_THAN=132
|
||||||
ASM_CURLY_BEGIN=133
|
ASM_GREATER_THAN=133
|
||||||
ASM_CURLY_END=134
|
ASM_MULTIPLY=134
|
||||||
ASM_NUMBER=135
|
ASM_DIVIDE=135
|
||||||
ASM_NUMFLOAT=136
|
ASM_CURLY_BEGIN=136
|
||||||
ASM_BINFLOAT=137
|
ASM_CURLY_END=137
|
||||||
ASM_DECFLOAT=138
|
ASM_NUMBER=138
|
||||||
ASM_HEXFLOAT=139
|
ASM_NUMFLOAT=139
|
||||||
ASM_NUMINT=140
|
ASM_BINFLOAT=140
|
||||||
ASM_BININTEGER=141
|
ASM_DECFLOAT=141
|
||||||
ASM_DECINTEGER=142
|
ASM_HEXFLOAT=142
|
||||||
ASM_HEXINTEGER=143
|
ASM_NUMINT=143
|
||||||
ASM_CHAR=144
|
ASM_BININTEGER=144
|
||||||
ASM_MULTI_REL=145
|
ASM_DECINTEGER=145
|
||||||
ASM_MULTI_NAME=146
|
ASM_HEXINTEGER=146
|
||||||
ASM_NAME=147
|
ASM_CHAR=147
|
||||||
ASM_WS=148
|
ASM_MULTI_REL=148
|
||||||
ASM_COMMENT_LINE=149
|
ASM_MULTI_NAME=149
|
||||||
ASM_COMMENT_BLOCK=150
|
ASM_NAME=150
|
||||||
|
ASM_WS=151
|
||||||
|
ASM_COMMENT_LINE=152
|
||||||
|
ASM_COMMENT_BLOCK=153
|
||||||
';'=8
|
';'=8
|
||||||
'..'=11
|
'..'=11
|
||||||
'?'=12
|
'?'=12
|
||||||
@ -209,19 +212,21 @@ ASM_COMMENT_BLOCK=150
|
|||||||
'enum'=79
|
'enum'=79
|
||||||
'sizeof'=80
|
'sizeof'=80
|
||||||
'typeid'=81
|
'typeid'=81
|
||||||
'kickasm'=82
|
'defined'=82
|
||||||
'resource'=83
|
'kickasm'=83
|
||||||
'uses'=84
|
'resource'=84
|
||||||
'clobbers'=85
|
'uses'=85
|
||||||
'bytes'=86
|
'clobbers'=86
|
||||||
'cycles'=87
|
'bytes'=87
|
||||||
'!'=88
|
'cycles'=88
|
||||||
'#define'=95
|
'!'=89
|
||||||
'\\\n'=96
|
'#define'=96
|
||||||
'#undef'=97
|
'#undef'=98
|
||||||
'#ifdef'=98
|
'#ifdef'=99
|
||||||
'#ifndef'=99
|
'#ifndef'=100
|
||||||
'#else'=100
|
'#if'=101
|
||||||
'#endif'=101
|
'#elif'=102
|
||||||
'.byte'=115
|
'#else'=103
|
||||||
'#'=117
|
'#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;
|
package dk.camelot64.kickc.parser;
|
||||||
|
|
||||||
|
|
||||||
@ -1273,6 +1273,18 @@ public class KickCParserBaseListener implements KickCParserListener {
|
|||||||
* <p>The default implementation does nothing.</p>
|
* <p>The default implementation does nothing.</p>
|
||||||
*/
|
*/
|
||||||
@Override public void exitExprId(KickCParser.ExprIdContext ctx) { }
|
@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}
|
* {@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;
|
package dk.camelot64.kickc.parser;
|
||||||
|
|
||||||
|
|
||||||
@ -748,6 +748,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
|||||||
* {@link #visitChildren} on {@code ctx}.</p>
|
* {@link #visitChildren} on {@code ctx}.</p>
|
||||||
*/
|
*/
|
||||||
@Override public T visitExprId(KickCParser.ExprIdContext ctx) { return visitChildren(ctx); }
|
@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}
|
* {@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;
|
package dk.camelot64.kickc.parser;
|
||||||
|
|
||||||
|
|
||||||
@ -1221,6 +1221,18 @@ public interface KickCParserListener extends ParseTreeListener {
|
|||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
*/
|
*/
|
||||||
void exitExprId(KickCParser.ExprIdContext ctx);
|
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}
|
* Enter a parse tree produced by the {@code exprTernary}
|
||||||
* labeled alternative in {@link KickCParser#expr}.
|
* 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;
|
package dk.camelot64.kickc.parser;
|
||||||
|
|
||||||
|
|
||||||
@ -723,6 +723,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
|||||||
* @return the visitor result
|
* @return the visitor result
|
||||||
*/
|
*/
|
||||||
T visitExprId(KickCParser.ExprIdContext ctx);
|
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}
|
* Visit a parse tree produced by the {@code exprTernary}
|
||||||
* labeled alternative in {@link KickCParser#expr}.
|
* labeled alternative in {@link KickCParser#expr}.
|
||||||
|
@ -1,8 +1,17 @@
|
|||||||
package dk.camelot64.kickc.preprocessor;
|
package dk.camelot64.kickc.preprocessor;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.NumberParser;
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
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.*;
|
||||||
|
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -22,18 +31,14 @@ public class CPreprocessor implements TokenSource {
|
|||||||
*/
|
*/
|
||||||
private Map<String, List<Token>> defines;
|
private Map<String, List<Token>> defines;
|
||||||
|
|
||||||
/** The token types. */
|
public CPreprocessor(TokenSource input, Map<String, List<Token>> defines) {
|
||||||
private CPreprocessorTokens tokenTypes;
|
|
||||||
|
|
||||||
public CPreprocessor(TokenSource input, CPreprocessorTokens tokenTypes) {
|
|
||||||
if(input instanceof CTokenSource) {
|
if(input instanceof CTokenSource) {
|
||||||
// If possible use the input directly instead of wrapping it
|
// If possible use the input directly instead of wrapping it
|
||||||
this.input = (CTokenSource) input;
|
this.input = (CTokenSource) input;
|
||||||
} else {
|
} else {
|
||||||
this.input = new CTokenSource(input);
|
this.input = new CTokenSource(input);
|
||||||
}
|
}
|
||||||
this.defines = new LinkedHashMap<>();
|
this.defines = defines;
|
||||||
this.tokenTypes = tokenTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
* @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) {
|
private boolean preprocess(Token inputToken, CTokenSource cTokenSource) {
|
||||||
if(inputToken.getType() == tokenTypes.define) {
|
if(inputToken.getType() == KickCLexer.DEFINE) {
|
||||||
define(cTokenSource);
|
define(cTokenSource);
|
||||||
return true;
|
return true;
|
||||||
} else if(inputToken.getType() == tokenTypes.undef) {
|
} else if(inputToken.getType() == KickCLexer.UNDEF) {
|
||||||
undef(cTokenSource);
|
undef(cTokenSource);
|
||||||
return true;
|
return true;
|
||||||
} else if(inputToken.getType() == tokenTypes.ifndef) {
|
} else if(inputToken.getType() == KickCLexer.IFNDEF) {
|
||||||
ifndef(cTokenSource);
|
ifndef(cTokenSource);
|
||||||
return true;
|
return true;
|
||||||
} else if(inputToken.getType() == tokenTypes.ifdef) {
|
} else if(inputToken.getType() == KickCLexer.IFDEF) {
|
||||||
ifdef(cTokenSource);
|
ifdef(cTokenSource);
|
||||||
return true;
|
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
|
// #else means we must skip until #endif
|
||||||
ifelse(cTokenSource);
|
ifelse(cTokenSource);
|
||||||
return true;
|
return true;
|
||||||
} else if(inputToken.getType() == tokenTypes.endif) {
|
} else if(inputToken.getType() == KickCLexer.ENDIF) {
|
||||||
// Skip #endif - they have already been handled by #if / #else
|
// Skip #endif - they have already been handled by #if / #else
|
||||||
return true;
|
return true;
|
||||||
} else if(inputToken.getType() == tokenTypes.identifier) {
|
} else if(inputToken.getType() == KickCLexer.NAME) {
|
||||||
final boolean expanded = expand(inputToken, cTokenSource);
|
return expand(inputToken, cTokenSource);
|
||||||
if(expanded)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -162,7 +168,7 @@ public class CPreprocessor implements TokenSource {
|
|||||||
private void undef(CTokenSource cTokenSource) {
|
private void undef(CTokenSource cTokenSource) {
|
||||||
// #undef a new macro - find the name
|
// #undef a new macro - find the name
|
||||||
skipWhitespace(cTokenSource);
|
skipWhitespace(cTokenSource);
|
||||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||||
this.defines.remove(macroName);
|
this.defines.remove(macroName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,13 +179,151 @@ public class CPreprocessor implements TokenSource {
|
|||||||
*/
|
*/
|
||||||
private void ifdef(CTokenSource cTokenSource) {
|
private void ifdef(CTokenSource cTokenSource) {
|
||||||
skipWhitespace(cTokenSource);
|
skipWhitespace(cTokenSource);
|
||||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||||
final boolean defined = this.defines.containsKey(macroName);
|
final boolean defined = this.defines.containsKey(macroName);
|
||||||
if(!defined) {
|
if(!defined) {
|
||||||
iffalse(cTokenSource);
|
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.
|
* #ifdef checks if a macro is _NOT_ defined.
|
||||||
*
|
*
|
||||||
@ -187,16 +331,16 @@ public class CPreprocessor implements TokenSource {
|
|||||||
*/
|
*/
|
||||||
private void ifndef(CTokenSource cTokenSource) {
|
private void ifndef(CTokenSource cTokenSource) {
|
||||||
skipWhitespace(cTokenSource);
|
skipWhitespace(cTokenSource);
|
||||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||||
final boolean defined = this.defines.containsKey(macroName);
|
final boolean defined = this.defines.containsKey(macroName);
|
||||||
if(defined) {
|
if(defined) {
|
||||||
iffalse(cTokenSource);
|
iffalse(cTokenSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip tokens based in an #if that is false
|
* Skip tokens based in an #if that is false
|
||||||
|
*
|
||||||
* @param cTokenSource The token source
|
* @param cTokenSource The token source
|
||||||
*/
|
*/
|
||||||
private void iffalse(CTokenSource cTokenSource) {
|
private void iffalse(CTokenSource cTokenSource) {
|
||||||
@ -205,14 +349,14 @@ public class CPreprocessor implements TokenSource {
|
|||||||
while(true) {
|
while(true) {
|
||||||
final Token token = cTokenSource.nextToken();
|
final Token token = cTokenSource.nextToken();
|
||||||
final int tokenType = token.getType();
|
final int tokenType = token.getType();
|
||||||
if(tokenType == tokenTypes.ifdef || tokenType == tokenTypes.ifndef) {
|
if(tokenType == KickCLexer.IFDEF || tokenType == KickCLexer.IFNDEF || tokenType == KickCLexer.IFIF) {
|
||||||
++nesting;
|
++nesting;
|
||||||
} else if(tokenType == tokenTypes.ifelse) {
|
} else if(tokenType == KickCLexer.IFELSE) {
|
||||||
if(nesting == 1) {
|
if(nesting == 1) {
|
||||||
// We are at the outer #if - #else means we must generate output from here!
|
// We are at the outer #if - #else means we must generate output from here!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if(tokenType == tokenTypes.endif) {
|
} else if(tokenType == KickCLexer.ENDIF) {
|
||||||
if(--nesting == 0) {
|
if(--nesting == 0) {
|
||||||
// We have passed the matching #endif - restart the output!
|
// We have passed the matching #endif - restart the output!
|
||||||
return;
|
return;
|
||||||
@ -231,9 +375,9 @@ public class CPreprocessor implements TokenSource {
|
|||||||
while(true) {
|
while(true) {
|
||||||
final Token token = cTokenSource.nextToken();
|
final Token token = cTokenSource.nextToken();
|
||||||
final int tokenType = token.getType();
|
final int tokenType = token.getType();
|
||||||
if(tokenType == tokenTypes.ifdef || tokenType == tokenTypes.ifndef) {
|
if(tokenType == KickCLexer.IFDEF || tokenType == KickCLexer.IFNDEF || tokenType == KickCLexer.IFIF) {
|
||||||
++nesting;
|
++nesting;
|
||||||
} else if(tokenType == tokenTypes.endif) {
|
} else if(tokenType == KickCLexer.ENDIF) {
|
||||||
if(--nesting == 0) {
|
if(--nesting == 0) {
|
||||||
// We have passed the matching #endif
|
// We have passed the matching #endif
|
||||||
return;
|
return;
|
||||||
@ -250,34 +394,45 @@ public class CPreprocessor implements TokenSource {
|
|||||||
private void define(CTokenSource cTokenSource) {
|
private void define(CTokenSource cTokenSource) {
|
||||||
// #define a new macro - find the name
|
// #define a new macro - find the name
|
||||||
skipWhitespace(cTokenSource);
|
skipWhitespace(cTokenSource);
|
||||||
String macroName = nextToken(cTokenSource, tokenTypes.identifier).getText();
|
String macroName = nextToken(cTokenSource, KickCLexer.NAME).getText();
|
||||||
// Examine whether the macro has parameters
|
// Examine whether the macro has parameters
|
||||||
skipWhitespace(cTokenSource);
|
skipWhitespace(cTokenSource);
|
||||||
if(cTokenSource.peekToken().getType() == tokenTypes.parBegin) {
|
if(cTokenSource.peekToken().getType() == KickCLexer.PAR_BEGIN) {
|
||||||
// Macro has parameters - find parameter name list
|
// Macro has parameters - find parameter name list
|
||||||
throw new CompileError("Macros with parameters not supported!");
|
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
|
// Find body by gobbling tokens until the line ends
|
||||||
final ArrayList<Token> macroBody = new ArrayList<>();
|
final ArrayList<Token> macroBody = new ArrayList<>();
|
||||||
while(true) {
|
while(true) {
|
||||||
final Token bodyToken = cTokenSource.nextToken();
|
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
|
// Skip the multi-line token, add a newline token and continue reading body on the next line
|
||||||
final CommonToken newlineToken = new CommonToken(bodyToken);
|
final CommonToken newlineToken = new CommonToken(bodyToken);
|
||||||
newlineToken.setType(tokenTypes.whitespace);
|
newlineToken.setType(KickCLexer.WS);
|
||||||
newlineToken.setChannel(tokenTypes.channelWhitespace);
|
newlineToken.setChannel(CParser.CHANNEL_WHITESPACE);
|
||||||
newlineToken.setText("\n");
|
newlineToken.setText("\n");
|
||||||
macroBody.add(newlineToken);
|
macroBody.add(newlineToken);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(bodyToken.getChannel() == tokenTypes.channelWhitespace && bodyToken.getText().contains("\n")) {
|
if(bodyToken.getChannel() == CParser.CHANNEL_WHITESPACE && bodyToken.getText().contains("\n")) {
|
||||||
// Done reading the body
|
// Done reading the body
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
macroBody.add(bodyToken);
|
macroBody.add(bodyToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defines.put(macroName, macroBody);
|
return macroBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,7 +457,7 @@ public class CPreprocessor implements TokenSource {
|
|||||||
private void skipWhitespace(CTokenSource cTokenSource) {
|
private void skipWhitespace(CTokenSource cTokenSource) {
|
||||||
while(true) {
|
while(true) {
|
||||||
final Token token = cTokenSource.peekToken();
|
final Token token = cTokenSource.peekToken();
|
||||||
if(token.getChannel() != tokenTypes.channelWhitespace)
|
if(token.getChannel() != CParser.CHANNEL_WHITESPACE)
|
||||||
break;
|
break;
|
||||||
if(token.getText().contains("\n"))
|
if(token.getText().contains("\n"))
|
||||||
break;
|
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;
|
package dk.camelot64.kickc.parsing.macros;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.parser.CParser;
|
||||||
import dk.camelot64.kickc.preprocessor.CPreprocessor;
|
import dk.camelot64.kickc.parser.KickCParser;
|
||||||
import dk.camelot64.kickc.preprocessor.CPreprocessorTokens;
|
import dk.camelot64.kickc.parser.KickCParserBaseVisitor;
|
||||||
import org.antlr.v4.runtime.*;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.CodePointCharStream;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
public class TestMacrosParser {
|
/**
|
||||||
|
* Test the C preprocessor
|
||||||
private int CHANNEL_WHITESPACE = 1;
|
*/
|
||||||
|
public class TestPreprocessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test some parsing without macros
|
* Test some parsing without macros
|
||||||
@ -36,6 +38,8 @@ public class TestMacrosParser {
|
|||||||
public void testSimpleDefine() {
|
public void testSimpleDefine() {
|
||||||
// A simple unused define
|
// A simple unused define
|
||||||
assertEquals("+(name:b,num:1);*(name:c,num:2);", parse("#define A a\nb+1;\nc*2;\n"));
|
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
|
// A simple used define
|
||||||
assertEquals("+(*(name:axe,num:2),name:axe);", parse("#define A axe\nA*2+A;"));
|
assertEquals("+(*(name:axe,num:2),name:axe);", parse("#define A axe\nA*2+A;"));
|
||||||
// A define using a special token class
|
// 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;"));
|
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
|
* Test define with parameters
|
||||||
*/
|
*/
|
||||||
@ -132,55 +177,27 @@ public class TestMacrosParser {
|
|||||||
* @return The parse-tree in string form
|
* @return The parse-tree in string form
|
||||||
*/
|
*/
|
||||||
private String parse(String program) {
|
private String parse(String program) {
|
||||||
final CharStream fileStream = CharStreams.fromString(program);
|
CodePointCharStream charStream = CharStreams.fromString(program);
|
||||||
// typedefs shared between lexer and parser
|
CParser cParser = new CParser(null);
|
||||||
MacrosLexer lexer = new MacrosLexer(fileStream);
|
cParser.addSource(charStream);
|
||||||
lexer.addErrorListener(new BaseErrorListener() {
|
KickCParser.StmtSeqContext stmtSeqContext = cParser.getParser().stmtSeq();
|
||||||
@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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
MacrosPrinter printVisitor = new MacrosPrinter();
|
MacrosPrinter printVisitor = new MacrosPrinter();
|
||||||
printVisitor.visit(parser.stmtSeq());
|
printVisitor.visit(stmtSeqContext);
|
||||||
return printVisitor.getOut().toString();
|
return printVisitor.getOut().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MacrosPrinter extends MacrosBaseVisitor<Object> {
|
private static class MacrosPrinter extends KickCParserBaseVisitor<Object> {
|
||||||
|
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
|
|
||||||
public StringBuilder getOut() {
|
StringBuilder getOut() {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitStmtSeq(MacrosParser.StmtSeqContext ctx) {
|
public Object visitStmtSeq(KickCParser.StmtSeqContext ctx) {
|
||||||
for(MacrosParser.StmtContext stmtContext : ctx.stmt()) {
|
for(KickCParser.StmtContext stmtContext : ctx.stmt()) {
|
||||||
this.visit(stmtContext);
|
this.visit(stmtContext);
|
||||||
out.append(";");
|
out.append(";");
|
||||||
}
|
}
|
||||||
@ -188,26 +205,20 @@ public class TestMacrosParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitStmtExpr(MacrosParser.StmtExprContext ctx) {
|
public Object visitExprId(KickCParser.ExprIdContext ctx) {
|
||||||
this.visit(ctx.expr());
|
out.append("name:").append(ctx.NAME().getText());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitExprName(MacrosParser.ExprNameContext ctx) {
|
public Object visitExprNumber(KickCParser.ExprNumberContext ctx) {
|
||||||
out.append("name:").append(ctx.getText());
|
return out.append("num:").append(ctx.NUMBER().getText());
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitExprNumber(MacrosParser.ExprNumberContext ctx) {
|
public Object visitExprCast(KickCParser.ExprCastContext ctx) {
|
||||||
return out.append("num:").append(ctx.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object visitExprCast(MacrosParser.ExprCastContext ctx) {
|
|
||||||
out.append("cast(");
|
out.append("cast(");
|
||||||
out.append(ctx.SIMPLETYPE().getText());
|
out.append(ctx.typeSpecifier().getText());
|
||||||
out.append(",");
|
out.append(",");
|
||||||
this.visit(ctx.expr());
|
this.visit(ctx.expr());
|
||||||
out.append(")");
|
out.append(")");
|
||||||
@ -215,7 +226,7 @@ public class TestMacrosParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitExprBinary(MacrosParser.ExprBinaryContext ctx) {
|
public Object visitExprBinary(KickCParser.ExprBinaryContext ctx) {
|
||||||
String fct = ctx.getChild(1).getText();
|
String fct = ctx.getChild(1).getText();
|
||||||
out.append(fct).append("(");
|
out.append(fct).append("(");
|
||||||
this.visit(ctx.expr(0));
|
this.visit(ctx.expr(0));
|
||||||
@ -225,11 +236,10 @@ public class TestMacrosParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitExprPar(MacrosParser.ExprParContext ctx) {
|
public Object visitExprPar(KickCParser.ExprParContext ctx) {
|
||||||
out.append("(");
|
out.append("(");
|
||||||
this.visit(ctx.expr());
|
this.visit(ctx.commaExpr());
|
||||||
out.append(")");
|
out.append(")");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user