1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-29 18:49:42 +00:00

Added javadoc to #pragmas.

This commit is contained in:
jespergravgaard 2021-12-30 14:29:58 +01:00
parent 9652931592
commit 385794ae99

View File

@ -2,10 +2,11 @@ package dk.camelot64.kickc.parser;
import dk.camelot64.kickc.FileNameUtils;
import dk.camelot64.kickc.SourceLoader;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.TargetPlatform;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.StringEncoding;
import dk.camelot64.kickc.passes.Pass4CodeGeneration;
import dk.camelot64.kickc.preprocessor.CPreprocessor;
import org.antlr.v4.runtime.*;
@ -24,55 +25,134 @@ import java.util.*;
public class CParser {
/** The hidden lexer channel containing whitespace. */
/**
* The hidden lexer channel containing whitespace.
*/
public static final int CHANNEL_WHITESPACE = 1;
/** The hidden lexer channel containing comments. */
/**
* The hidden lexer channel containing comments.
*/
public static final int CHANNEL_COMMENTS = 2;
/** Pragma Names. */
/**
* #pragma target(...) selects the target platform to compile for.
* See {@link TargetPlatform}.
*/
public static final String PRAGMA_TARGET = "target";
/**
* #pragma cpu(...) selects which CPU to compile for. See {@link TargetCpu}.
*/
public static final String PRAGMA_CPU = "cpu";
/**
* #pragma var_model(...) configures how different variables should be compiled.
* See {@link VariableBuilderConfig}.
*/
public static final String PRAGMA_VAR_MODEL = "var_model";
/**
* #pragma link("filename") selects a custom linker file.
* See {@link Pass4CodeGeneration#generate()}
*/
public static final String PRAGMA_LINKSCRIPT = "link";
/**
* #pragma extension(...) specifies the extension of the generated binary output file.
*/
public static final String PRAGMA_EXTENSION = "extension";
/**
* #pragma emulator(...) specifies which emulator to run when executing the binary program.
*/
public static final String PRAGMA_EMULATOR = "emulator";
/**
* #pragma encoding(...) specifies which character encoding to use for strings and chars.
* See {@link StringEncoding}.
*/
public static final String PRAGMA_ENCODING = "encoding";
/**
* #pragma code_seg(...) changes the current code segment. Segments are defined in the linker file.
*/
public static final String PRAGMA_CODE_SEG = "code_seg";
/**
* #pragma data_seg(...) changes the current data segment. Segments are defined in the linker file.
*/
public static final String PRAGMA_DATA_SEG = "data_seg";
/**
* #pragma start_address(...) specifies the start address of the program.
*/
public static final String PRAGMA_START_ADDRESS = "start_address";
/**
* #pragma calling(...) specifies which default calling convention to use for functions.
* See {@link Procedure.CallingConvention}.
*/
public static final String PRAGMA_CALLING = "calling";
/**
* #pragma zp_reserve(...) specifies that some zeropage-addresses should be reserved preventing the
* compiler from allocating variables to those addresses.
*/
public static final String PRAGMA_ZP_RESERVE = "zp_reserve";
/**
* #pragma constructor_for(...) specifies that a certain function is an
* initializer for a library and must be called before main().
*/
public static final String PRAGMA_CONSTRUCTOR_FOR = "constructor_for";
/**
* #pragma interrupt(...) specifies the default interrupt type to use for functions marked with __interrupt.
*/
public static final String PRAGMA_INTERRUPT = "interrupt";
/**
* #pragma struct_model(...) sepcifies which struct model to use by default.
*/
public static final String PRAGMA_STRUCT_MODEL = "struct_model";
/**
* #pragma resource("filename") specifies that a specific file is a resource that is needed for assembly.
* The resource-file is copied to the output directory when compiling.
*/
public static final String PRAGMA_RESOURCE = "resource";
/** The Program. */
/**
* The Program.
*/
private Program program;
/** The (single) parser. */
/**
* The (single) parser.
*/
private KickCParser parser;
/** The preprocessor. */
/**
* The preprocessor.
*/
private CPreprocessor preprocessor;
/** The token stream. */
/**
* The token stream.
*/
private final CommonTokenStream preprocessedTokenStream;
/** The token source stack handling import files. */
/**
* The token source stack handling import files.
*/
private CTokenSource cTokenSource;
/** The input files that have been parsed. Maps file name to the lexer. */
/**
* The input files that have been parsed. Maps file name to the lexer.
*/
private Map<String, CFile> cFiles;
/** Names of typedefs. Used by lexer to know the difference between normal value IDENTIFIERS and TYPEIDENTIFIERS */
/**
* Names of typedefs. Used by lexer to know the difference between normal value IDENTIFIERS and TYPEIDENTIFIERS
*/
private List<String> typedefs;
/** A C-file that has been imported & parsed. */
/**
* A C-file that has been imported & parsed.
*/
public static class CFile {
/** The source file currently being parsed. */
/**
* The source file currently being parsed.
*/
private File file;
/** The lexer. */
/**
* The lexer.
*/
private KickCLexer lexer;
CFile(File file, KickCLexer lexer) {
@ -199,12 +279,12 @@ public class CParser {
* @param fileName The file name of the file
*/
public void includeCFile(String fileName, boolean isSystem) {
if(fileName.startsWith("\"") || fileName.startsWith("<")) {
if (fileName.startsWith("\"") || fileName.startsWith("<")) {
fileName = fileName.substring(1, fileName.length() - 1);
}
final Path currentSourceFolderPath = isSystem ? null : getCurrentSourceFolderPath();
final TokenSource fileTokens = loadCFile(fileName, currentSourceFolderPath, program.getIncludePaths(), false);
if(fileName.endsWith(".h")) {
if (fileName.endsWith(".h")) {
// The included file was a H-file - attempt to find the matching library C-file
String libFileName = FileNameUtils.removeExtension(fileName) + ".c";
final TokenSource cLibFileTokens = loadCFile(libFileName, currentSourceFolderPath, program.getLibraryPaths(), true);
@ -224,19 +304,19 @@ public class CParser {
public TokenSource loadCFile(String fileName, Path currentPath, List<String> searchPaths, boolean acceptFileNotFound) {
try {
File file = SourceLoader.loadFile(fileName, currentPath, searchPaths);
if(file == null)
if(acceptFileNotFound)
if (file == null)
if (acceptFileNotFound)
return null;
else
throw new CompileError("File not found " + fileName);
Path filePath = file.toPath().toAbsolutePath().normalize();
List<String> included = program.getLoadedFiles();
if(included.contains(filePath.toString())) {
if (included.contains(filePath.toString())) {
return null;
}
final CharStream fileStream = CharStreams.fromPath(filePath);
included.add(filePath.toString());
if(program.getLog().isVerboseParse()) {
if (program.getLog().isVerboseParse()) {
program.getLog().append("PARSING " + filePath.toString().replace("\\", "/"));
program.getLog().append(fileStream.toString());
}
@ -244,7 +324,7 @@ public class CParser {
CFile cFile = new CFile(file, lexer);
cFiles.put(filePath.toString(), cFile);
return lexer;
} catch(IOException e) {
} catch (IOException e) {
throw new CompileError("Error parsing file " + fileName, e);
}
}
@ -260,8 +340,8 @@ public class CParser {
final TargetPlatform targetPlatform = loadPlatformFile(platformName, currentPath, program.getTargetPlatformPaths());
// Remove macros from existing platform!
if(program.getTargetPlatform() != null && program.getTargetPlatform().getDefines() != null)
for(String macroName : program.getTargetPlatform().getDefines().keySet())
if (program.getTargetPlatform() != null && program.getTargetPlatform().getDefines() != null)
for (String macroName : program.getTargetPlatform().getDefines().keySet())
preprocessor.undef(macroName);
// Remove reserved ZP's from existing platform
program.getReservedZps().removeAll(program.getTargetPlatform().getReservedZps());
@ -269,8 +349,8 @@ public class CParser {
// Set the new program platform
program.setTargetPlatform(targetPlatform);
// Define macros from new platform!
if(program.getTargetPlatform().getDefines() != null)
for(String macroName : program.getTargetPlatform().getDefines().keySet())
if (program.getTargetPlatform().getDefines() != null)
for (String macroName : program.getTargetPlatform().getDefines().keySet())
define(macroName, program.getTargetPlatform().getDefines().get(macroName));
// Add reserved ZP's from new platform
program.addReservedZps(program.getTargetPlatform().getReservedZps());
@ -281,6 +361,7 @@ public class CParser {
/**
* Load a platform file and produce an error if it cannot be found.
*
* @param platformName The platform name
* @param currentPath The current path
* @param targetPlatformPaths The search list of paths to look through
@ -288,10 +369,10 @@ public class CParser {
*/
public static TargetPlatform loadPlatformFile(String platformName, Path currentPath, List<String> targetPlatformPaths) {
final File platformFile = SourceLoader.loadFile(platformName + "." + CTargetPlatformParser.FILE_EXTENSION, currentPath, targetPlatformPaths);
if(platformFile == null) {
if (platformFile == null) {
StringBuilder supported = new StringBuilder();
final List<File> platformFiles = SourceLoader.listFiles(currentPath, targetPlatformPaths, CTargetPlatformParser.FILE_EXTENSION);
for(File file : platformFiles) {
for (File file : platformFiles) {
String name = file.getName();
name = name.substring(0, name.length() - CTargetPlatformParser.FILE_EXTENSION.length() - 1);
supported.append(name).append(" ");
@ -332,7 +413,7 @@ public class CParser {
* @param tokenSource The lexer for reading the source tokens
*/
public void addSourceFirst(TokenSource tokenSource) {
if(tokenSource != null)
if (tokenSource != null)
cTokenSource.addSourceFirst(tokenSource);
}
@ -342,7 +423,7 @@ public class CParser {
* @param tokenSource The lexer for reading the source tokens
*/
public void addSourceLast(TokenSource tokenSource) {
if(tokenSource != null)
if (tokenSource != null)
cTokenSource.addSourceLast(tokenSource);
}