1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added Typedef parser and test-case that illustrates the typedef ambiguity problem. #269

This commit is contained in:
jespergravgaard 2019-08-21 10:13:15 +02:00
parent 67a9880b94
commit 8743921cd9
10 changed files with 1240 additions and 0 deletions

View File

@ -0,0 +1,129 @@
package dk.camelot64.kickc.parsing;
import dk.camelot64.kickc.model.CompileError;
import org.antlr.v4.runtime.*;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestTypedefParser {
@Test
public void testExprParser() {
// a & b are not types - resolving to values
assertEquals("and(val:a,val:b)", parseExprTypedef("a&b"));
// a & b are not types - resolving to values even with added parenthesis (looking like a cast)
assertEquals("and((val:a),val:b)", parseExprTypedef("(a)&b"));
// char is a simple type - resolving to cast of simple type
assertEquals("cast(simpletype:char,addressof(val:b))", parseExprTypedef("(char)&b"));
// T is typedeffed - so this should resolve to a cast of typedef
assertEquals("cast(typedef:T,addressof(val:b))", parseExprTypedef("(T)&b"));
}
/**
* Parse a Typedef expression and return the resulting syntax tree
*
* @param expr The Typedef expression to parse
* @return The parse-tree in string form
*/
private String parseExprTypedef(String expr) {
final CharStream fileStream = CharStreams.fromString(expr);
TypedefLexer lexer = new TypedefLexer(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);
}
});
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
TypedefParser parser = new TypedefParser(tokenStream);
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);
}
});
TypedefPrinter printVisitor = new TypedefPrinter();
printVisitor.visit(parser.expr());
return printVisitor.getOut().toString();
}
private static class TypedefPrinter extends TypedefBaseVisitor<Object> {
StringBuilder out = new StringBuilder();
public StringBuilder getOut() {
return out;
}
@Override
public Object visitExprValueName(TypedefParser.ExprValueNameContext ctx) {
out.append("val:").append(ctx.getText());
return null;
}
@Override
public Object visitExprCast(TypedefParser.ExprCastContext ctx) {
out.append("cast(");
this.visit(ctx.typeName());
out.append(",");
this.visit(ctx.expr());
out.append(")");
return null;
}
@Override
public Object visitExprAnd(TypedefParser.ExprAndContext ctx) {
out.append("and(");
this.visit(ctx.expr(0));
out.append(",");
this.visit(ctx.expr(1));
out.append(")");
return null;
}
@Override
public Object visitExprAddressOf(TypedefParser.ExprAddressOfContext ctx) {
out.append("addressof(");
this.visit(ctx.expr());
out.append(")");
return null;
}
@Override
public Object visitExprParenthesis(TypedefParser.ExprParenthesisContext ctx) {
out.append("(");
this.visit(ctx.expr());
out.append(")");
return null;
}
@Override
public Object visitTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx) {
out.append("simpletype:").append(ctx.SIMPLETYPE().getText());
return null;
}
@Override
public Object visitTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx) {
out.append("typedef:").append(ctx.getText());
return null;
}
}
}

View File

@ -0,0 +1,58 @@
/*
[The "BSD licence"]
Copyright (c) 2013 Sam Harwell
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** C 2011 grammar built from the C11 Spec */
grammar Typedef;
expr
: valueName #exprValueName
| '(' expr ')' #exprParenthesis
| '&' expr #exprAddressOf
| expr '&' expr #exprAnd
| '(' typeName ')' expr #exprCast
;
typeName
: SIMPLETYPE #typeNameSimple
| typedefName #typeNameTypedef
;
typedefName
: IDENTIFIER
;
valueName
: IDENTIFIER
;
SIMPLETYPE: 'char' | 'int';
IDENTIFIER : [a-zA-Z_]+ ;
WHITESPACE
: [ \t\r\n]+
-> skip
;

View File

@ -0,0 +1,9 @@
T__0=1
T__1=2
T__2=3
SIMPLETYPE=4
IDENTIFIER=5
WHITESPACE=6
'('=1
')'=2
'&'=3

View File

@ -0,0 +1,147 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/Typedef.g4 by ANTLR 4.7
package dk.camelot64.kickc.parsing;
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 TypedefListener},
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
public class TypedefBaseListener implements TypedefListener {
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExprValueName(TypedefParser.ExprValueNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprValueName(TypedefParser.ExprValueNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExprCast(TypedefParser.ExprCastContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprCast(TypedefParser.ExprCastContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExprAnd(TypedefParser.ExprAndContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprAnd(TypedefParser.ExprAndContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExprAddressOf(TypedefParser.ExprAddressOfContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprAddressOf(TypedefParser.ExprAddressOfContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExprParenthesis(TypedefParser.ExprParenthesisContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprParenthesis(TypedefParser.ExprParenthesisContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypedefName(TypedefParser.TypedefNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypedefName(TypedefParser.TypedefNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterValueName(TypedefParser.ValueNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitValueName(TypedefParser.ValueNameContext 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) { }
}

View File

@ -0,0 +1,77 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/Typedef.g4 by ANTLR 4.7
package dk.camelot64.kickc.parsing;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link TypedefVisitor},
* 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 TypedefBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements TypedefVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprValueName(TypedefParser.ExprValueNameContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprCast(TypedefParser.ExprCastContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprAnd(TypedefParser.ExprAndContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprAddressOf(TypedefParser.ExprAddressOfContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprParenthesis(TypedefParser.ExprParenthesisContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypedefName(TypedefParser.TypedefNameContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValueName(TypedefParser.ValueNameContext ctx) { return visitChildren(ctx); }
}

View File

@ -0,0 +1,117 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/Typedef.g4 by ANTLR 4.7
package dk.camelot64.kickc.parsing;
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 TypedefLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7", 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, SIMPLETYPE=4, IDENTIFIER=5, WHITESPACE=6;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static String[] modeNames = {
"DEFAULT_MODE"
};
public static final String[] ruleNames = {
"T__0", "T__1", "T__2", "SIMPLETYPE", "IDENTIFIER", "WHITESPACE"
};
private static final String[] _LITERAL_NAMES = {
null, "'('", "')'", "'&'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, "SIMPLETYPE", "IDENTIFIER", "WHITESPACE"
};
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 TypedefLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "Typedef.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\b*\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\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5"+
"\3\5\3\5\3\5\3\5\3\5\5\5\35\n\5\3\6\6\6 \n\6\r\6\16\6!\3\7\6\7%\n\7\r"+
"\7\16\7&\3\7\3\7\2\2\b\3\3\5\4\7\5\t\6\13\7\r\b\3\2\4\5\2C\\aac|\5\2\13"+
"\f\17\17\"\"\2,\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\3\17\3\2\2\2\5\21\3\2\2\2\7\23\3\2\2\2\t\34\3\2\2\2"+
"\13\37\3\2\2\2\r$\3\2\2\2\17\20\7*\2\2\20\4\3\2\2\2\21\22\7+\2\2\22\6"+
"\3\2\2\2\23\24\7(\2\2\24\b\3\2\2\2\25\26\7e\2\2\26\27\7j\2\2\27\30\7c"+
"\2\2\30\35\7t\2\2\31\32\7k\2\2\32\33\7p\2\2\33\35\7v\2\2\34\25\3\2\2\2"+
"\34\31\3\2\2\2\35\n\3\2\2\2\36 \t\2\2\2\37\36\3\2\2\2 !\3\2\2\2!\37\3"+
"\2\2\2!\"\3\2\2\2\"\f\3\2\2\2#%\t\3\2\2$#\3\2\2\2%&\3\2\2\2&$\3\2\2\2"+
"&\'\3\2\2\2\'(\3\2\2\2()\b\7\2\2)\16\3\2\2\2\6\2\34!&\3\b\2\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);
}
}
}

View File

@ -0,0 +1,9 @@
T__0=1
T__1=2
T__2=3
SIMPLETYPE=4
IDENTIFIER=5
WHITESPACE=6
'('=1
')'=2
'&'=3

View File

@ -0,0 +1,114 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/Typedef.g4 by ANTLR 4.7
package dk.camelot64.kickc.parsing;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link TypedefParser}.
*/
public interface TypedefListener extends ParseTreeListener {
/**
* Enter a parse tree produced by the {@code exprValueName}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void enterExprValueName(TypedefParser.ExprValueNameContext ctx);
/**
* Exit a parse tree produced by the {@code exprValueName}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void exitExprValueName(TypedefParser.ExprValueNameContext ctx);
/**
* Enter a parse tree produced by the {@code exprCast}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void enterExprCast(TypedefParser.ExprCastContext ctx);
/**
* Exit a parse tree produced by the {@code exprCast}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void exitExprCast(TypedefParser.ExprCastContext ctx);
/**
* Enter a parse tree produced by the {@code exprAnd}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void enterExprAnd(TypedefParser.ExprAndContext ctx);
/**
* Exit a parse tree produced by the {@code exprAnd}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void exitExprAnd(TypedefParser.ExprAndContext ctx);
/**
* Enter a parse tree produced by the {@code exprAddressOf}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void enterExprAddressOf(TypedefParser.ExprAddressOfContext ctx);
/**
* Exit a parse tree produced by the {@code exprAddressOf}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void exitExprAddressOf(TypedefParser.ExprAddressOfContext ctx);
/**
* Enter a parse tree produced by the {@code exprParenthesis}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void enterExprParenthesis(TypedefParser.ExprParenthesisContext ctx);
/**
* Exit a parse tree produced by the {@code exprParenthesis}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
*/
void exitExprParenthesis(TypedefParser.ExprParenthesisContext ctx);
/**
* Enter a parse tree produced by the {@code typeNameSimple}
* labeled alternative in {@link TypedefParser#typeName}.
* @param ctx the parse tree
*/
void enterTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx);
/**
* Exit a parse tree produced by the {@code typeNameSimple}
* labeled alternative in {@link TypedefParser#typeName}.
* @param ctx the parse tree
*/
void exitTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx);
/**
* Enter a parse tree produced by the {@code typeNameTypedef}
* labeled alternative in {@link TypedefParser#typeName}.
* @param ctx the parse tree
*/
void enterTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx);
/**
* Exit a parse tree produced by the {@code typeNameTypedef}
* labeled alternative in {@link TypedefParser#typeName}.
* @param ctx the parse tree
*/
void exitTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx);
/**
* Enter a parse tree produced by {@link TypedefParser#typedefName}.
* @param ctx the parse tree
*/
void enterTypedefName(TypedefParser.TypedefNameContext ctx);
/**
* Exit a parse tree produced by {@link TypedefParser#typedefName}.
* @param ctx the parse tree
*/
void exitTypedefName(TypedefParser.TypedefNameContext ctx);
/**
* Enter a parse tree produced by {@link TypedefParser#valueName}.
* @param ctx the parse tree
*/
void enterValueName(TypedefParser.ValueNameContext ctx);
/**
* Exit a parse tree produced by {@link TypedefParser#valueName}.
* @param ctx the parse tree
*/
void exitValueName(TypedefParser.ValueNameContext ctx);
}

View File

@ -0,0 +1,506 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/Typedef.g4 by ANTLR 4.7
package dk.camelot64.kickc.parsing;
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 TypedefParser extends Parser {
static { RuntimeMetaData.checkVersion("4.7", 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, SIMPLETYPE=4, IDENTIFIER=5, WHITESPACE=6;
public static final int
RULE_expr = 0, RULE_typeName = 1, RULE_typedefName = 2, RULE_valueName = 3;
public static final String[] ruleNames = {
"expr", "typeName", "typedefName", "valueName"
};
private static final String[] _LITERAL_NAMES = {
null, "'('", "')'", "'&'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, "SIMPLETYPE", "IDENTIFIER", "WHITESPACE"
};
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 "Typedef.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public ATN getATN() { return _ATN; }
public TypedefParser(TokenStream input) {
super(input);
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
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 ExprValueNameContext extends ExprContext {
public ValueNameContext valueName() {
return getRuleContext(ValueNameContext.class,0);
}
public ExprValueNameContext(ExprContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterExprValueName(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitExprValueName(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitExprValueName(this);
else return visitor.visitChildren(this);
}
}
public static class ExprCastContext extends ExprContext {
public TypeNameContext typeName() {
return getRuleContext(TypeNameContext.class,0);
}
public ExprContext expr() {
return getRuleContext(ExprContext.class,0);
}
public ExprCastContext(ExprContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterExprCast(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitExprCast(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitExprCast(this);
else return visitor.visitChildren(this);
}
}
public static class ExprAndContext extends ExprContext {
public List<ExprContext> expr() {
return getRuleContexts(ExprContext.class);
}
public ExprContext expr(int i) {
return getRuleContext(ExprContext.class,i);
}
public ExprAndContext(ExprContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterExprAnd(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitExprAnd(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitExprAnd(this);
else return visitor.visitChildren(this);
}
}
public static class ExprAddressOfContext extends ExprContext {
public ExprContext expr() {
return getRuleContext(ExprContext.class,0);
}
public ExprAddressOfContext(ExprContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterExprAddressOf(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitExprAddressOf(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitExprAddressOf(this);
else return visitor.visitChildren(this);
}
}
public static class ExprParenthesisContext extends ExprContext {
public ExprContext expr() {
return getRuleContext(ExprContext.class,0);
}
public ExprParenthesisContext(ExprContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterExprParenthesis(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitExprParenthesis(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitExprParenthesis(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 = 0;
enterRecursionRule(_localctx, 0, RULE_expr, _p);
try {
int _alt;
enterOuterAlt(_localctx, 1);
{
setState(21);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,0,_ctx) ) {
case 1:
{
_localctx = new ExprValueNameContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(9);
valueName();
}
break;
case 2:
{
_localctx = new ExprParenthesisContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(10);
match(T__0);
setState(11);
expr(0);
setState(12);
match(T__1);
}
break;
case 3:
{
_localctx = new ExprAddressOfContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(14);
match(T__2);
setState(15);
expr(3);
}
break;
case 4:
{
_localctx = new ExprCastContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(16);
match(T__0);
setState(17);
typeName();
setState(18);
match(T__1);
setState(19);
expr(1);
}
break;
}
_ctx.stop = _input.LT(-1);
setState(28);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,1,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
if ( _parseListeners!=null ) triggerExitRuleEvent();
_prevctx = _localctx;
{
{
_localctx = new ExprAndContext(new ExprContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expr);
setState(23);
if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
setState(24);
match(T__2);
setState(25);
expr(3);
}
}
}
setState(30);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,1,_ctx);
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
unrollRecursionContexts(_parentctx);
}
return _localctx;
}
public static class TypeNameContext extends ParserRuleContext {
public TypeNameContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_typeName; }
public TypeNameContext() { }
public void copyFrom(TypeNameContext ctx) {
super.copyFrom(ctx);
}
}
public static class TypeNameTypedefContext extends TypeNameContext {
public TypedefNameContext typedefName() {
return getRuleContext(TypedefNameContext.class,0);
}
public TypeNameTypedefContext(TypeNameContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterTypeNameTypedef(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitTypeNameTypedef(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitTypeNameTypedef(this);
else return visitor.visitChildren(this);
}
}
public static class TypeNameSimpleContext extends TypeNameContext {
public TerminalNode SIMPLETYPE() { return getToken(TypedefParser.SIMPLETYPE, 0); }
public TypeNameSimpleContext(TypeNameContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterTypeNameSimple(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitTypeNameSimple(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitTypeNameSimple(this);
else return visitor.visitChildren(this);
}
}
public final TypeNameContext typeName() throws RecognitionException {
TypeNameContext _localctx = new TypeNameContext(_ctx, getState());
enterRule(_localctx, 2, RULE_typeName);
try {
setState(33);
_errHandler.sync(this);
switch (_input.LA(1)) {
case SIMPLETYPE:
_localctx = new TypeNameSimpleContext(_localctx);
enterOuterAlt(_localctx, 1);
{
setState(31);
match(SIMPLETYPE);
}
break;
case IDENTIFIER:
_localctx = new TypeNameTypedefContext(_localctx);
enterOuterAlt(_localctx, 2);
{
setState(32);
typedefName();
}
break;
default:
throw new NoViableAltException(this);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class TypedefNameContext extends ParserRuleContext {
public TerminalNode IDENTIFIER() { return getToken(TypedefParser.IDENTIFIER, 0); }
public TypedefNameContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_typedefName; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterTypedefName(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitTypedefName(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitTypedefName(this);
else return visitor.visitChildren(this);
}
}
public final TypedefNameContext typedefName() throws RecognitionException {
TypedefNameContext _localctx = new TypedefNameContext(_ctx, getState());
enterRule(_localctx, 4, RULE_typedefName);
try {
enterOuterAlt(_localctx, 1);
{
setState(35);
match(IDENTIFIER);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class ValueNameContext extends ParserRuleContext {
public TerminalNode IDENTIFIER() { return getToken(TypedefParser.IDENTIFIER, 0); }
public ValueNameContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_valueName; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).enterValueName(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TypedefListener ) ((TypedefListener)listener).exitValueName(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof TypedefVisitor ) return ((TypedefVisitor<? extends T>)visitor).visitValueName(this);
else return visitor.visitChildren(this);
}
}
public final ValueNameContext valueName() throws RecognitionException {
ValueNameContext _localctx = new ValueNameContext(_ctx, getState());
enterRule(_localctx, 6, RULE_valueName);
try {
enterOuterAlt(_localctx, 1);
{
setState(37);
match(IDENTIFIER);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
switch (ruleIndex) {
case 0:
return expr_sempred((ExprContext)_localctx, predIndex);
}
return true;
}
private boolean expr_sempred(ExprContext _localctx, int predIndex) {
switch (predIndex) {
case 0:
return precpred(_ctx, 2);
}
return true;
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\b*\4\2\t\2\4\3\t"+
"\3\4\4\t\4\4\5\t\5\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2"+
"\5\2\30\n\2\3\2\3\2\3\2\7\2\35\n\2\f\2\16\2 \13\2\3\3\3\3\5\3$\n\3\3\4"+
"\3\4\3\5\3\5\3\5\2\3\2\6\2\4\6\b\2\2\2*\2\27\3\2\2\2\4#\3\2\2\2\6%\3\2"+
"\2\2\b\'\3\2\2\2\n\13\b\2\1\2\13\30\5\b\5\2\f\r\7\3\2\2\r\16\5\2\2\2\16"+
"\17\7\4\2\2\17\30\3\2\2\2\20\21\7\5\2\2\21\30\5\2\2\5\22\23\7\3\2\2\23"+
"\24\5\4\3\2\24\25\7\4\2\2\25\26\5\2\2\3\26\30\3\2\2\2\27\n\3\2\2\2\27"+
"\f\3\2\2\2\27\20\3\2\2\2\27\22\3\2\2\2\30\36\3\2\2\2\31\32\f\4\2\2\32"+
"\33\7\5\2\2\33\35\5\2\2\5\34\31\3\2\2\2\35 \3\2\2\2\36\34\3\2\2\2\36\37"+
"\3\2\2\2\37\3\3\2\2\2 \36\3\2\2\2!$\7\6\2\2\"$\5\6\4\2#!\3\2\2\2#\"\3"+
"\2\2\2$\5\3\2\2\2%&\7\7\2\2&\7\3\2\2\2\'(\7\7\2\2(\t\3\2\2\2\5\27\36#";
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);
}
}
}

View File

@ -0,0 +1,74 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/test/java/dk/camelot64/kickc/parsing/Typedef.g4 by ANTLR 4.7
package dk.camelot64.kickc.parsing;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
/**
* This interface defines a complete generic visitor for a parse tree produced
* by {@link TypedefParser}.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public interface TypedefVisitor<T> extends ParseTreeVisitor<T> {
/**
* Visit a parse tree produced by the {@code exprValueName}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprValueName(TypedefParser.ExprValueNameContext ctx);
/**
* Visit a parse tree produced by the {@code exprCast}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprCast(TypedefParser.ExprCastContext ctx);
/**
* Visit a parse tree produced by the {@code exprAnd}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprAnd(TypedefParser.ExprAndContext ctx);
/**
* Visit a parse tree produced by the {@code exprAddressOf}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprAddressOf(TypedefParser.ExprAddressOfContext ctx);
/**
* Visit a parse tree produced by the {@code exprParenthesis}
* labeled alternative in {@link TypedefParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprParenthesis(TypedefParser.ExprParenthesisContext ctx);
/**
* Visit a parse tree produced by the {@code typeNameSimple}
* labeled alternative in {@link TypedefParser#typeName}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeNameSimple(TypedefParser.TypeNameSimpleContext ctx);
/**
* Visit a parse tree produced by the {@code typeNameTypedef}
* labeled alternative in {@link TypedefParser#typeName}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeNameTypedef(TypedefParser.TypeNameTypedefContext ctx);
/**
* Visit a parse tree produced by {@link TypedefParser#typedefName}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypedefName(TypedefParser.TypedefNameContext ctx);
/**
* Visit a parse tree produced by {@link TypedefParser#valueName}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitValueName(TypedefParser.ValueNameContext ctx);
}