mirror of
https://github.com/irmen/prog8.git
synced 2025-03-17 16:29:52 +00:00
simplify grammar of @tags, also improving their error message
This commit is contained in:
parent
131d5ceb4f
commit
5482ac0302
@ -414,7 +414,7 @@ internal fun determineCompilationOptions(program: Program, compTarget: ICompilat
|
||||
private fun processAst(program: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||
program.preprocessAst(errors, compilerOptions)
|
||||
|
||||
if(compilerOptions.dumpSymbols) {
|
||||
if(errors.noErrors() && compilerOptions.dumpSymbols) {
|
||||
printSymbols(program)
|
||||
exitProcess(0)
|
||||
}
|
||||
|
@ -56,6 +56,12 @@ class AstPreprocessor(val program: Program,
|
||||
vardecl.value = NumericLiteral(oldAddr.type, address.toDouble(), oldAddr.position)
|
||||
}
|
||||
|
||||
override fun before(directive: Directive, parent: Node): Iterable<IAstModification> {
|
||||
if(directive.parent is Expression)
|
||||
errors.err("${directive.directive} is ambiguous here as an operand for the % operator and a directive. Add spaces around the operator % to distinguish it.", directive.position)
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(char: CharLiteral, parent: Node): Iterable<IAstModification> {
|
||||
if(char.encoding== Encoding.DEFAULT)
|
||||
char.encoding = char.definingModule.textEncoding
|
||||
|
@ -756,9 +756,9 @@ main {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
ubyte bb1 = 199
|
||||
ubyte bb2 = 12
|
||||
ubyte @shared bb3 = bb1%bb2
|
||||
ubyte @shared bb = 199
|
||||
ubyte @shared cc = 12
|
||||
ubyte @shared bb2 = bb%cc
|
||||
}
|
||||
}"""
|
||||
|
||||
|
@ -332,12 +332,13 @@ private fun SubroutineContext.toAst() : Subroutine {
|
||||
private fun Sub_paramsContext.toAst(): List<SubroutineParameter> =
|
||||
sub_param().map {
|
||||
val decl = it.vardecl()
|
||||
val options = decl.decloptions()
|
||||
if(options.ALIGNPAGE().isNotEmpty() || options.ALIGNWORD().isNotEmpty())
|
||||
throw SyntaxError("cannot use alignments on parameters", it.toPosition())
|
||||
if(options.DIRTY().isNotEmpty())
|
||||
throw SyntaxError("cannot use @dirty on parameters", it.toPosition())
|
||||
val zp = getZpOption(options)
|
||||
val tags = decl.TAG().map { it.text }
|
||||
val validTags = arrayOf("@zp", "@requirezp", "@nozp", "@split", "@nosplit", "@shared")
|
||||
for(tag in tags) {
|
||||
if(tag !in validTags)
|
||||
throw SyntaxError("invalid parameter tag '$tag'", toPosition())
|
||||
}
|
||||
val zp = getZpOption(tags)
|
||||
var baseDt = decl.datatype()?.toAst() ?: BaseDataType.UNDEFINED
|
||||
var datatype = DataType.forDt(baseDt)
|
||||
if(decl.ARRAYSIG()!=null || decl.arrayindex()!=null)
|
||||
@ -355,23 +356,17 @@ private fun Sub_paramsContext.toAst(): List<SubroutineParameter> =
|
||||
SubroutineParameter(identifiername.text, datatype, zp, registerorpair, it.toPosition())
|
||||
}
|
||||
|
||||
private fun getZpOption(options: DecloptionsContext?): ZeropageWish {
|
||||
if(options==null)
|
||||
return ZeropageWish.DONTCARE
|
||||
return when {
|
||||
options.ZEROPAGEREQUIRE().isNotEmpty() -> ZeropageWish.REQUIRE_ZEROPAGE
|
||||
options.ZEROPAGE().isNotEmpty() -> ZeropageWish.PREFER_ZEROPAGE
|
||||
options.ZEROPAGENOT().isNotEmpty() -> ZeropageWish.NOT_IN_ZEROPAGE
|
||||
else -> ZeropageWish.DONTCARE
|
||||
}
|
||||
private fun getZpOption(tags: List<String>): ZeropageWish = when {
|
||||
"@requirezp" in tags -> ZeropageWish.REQUIRE_ZEROPAGE
|
||||
"@zp" in tags -> ZeropageWish.PREFER_ZEROPAGE
|
||||
"@nozp" in tags -> ZeropageWish.NOT_IN_ZEROPAGE
|
||||
else -> ZeropageWish.DONTCARE
|
||||
}
|
||||
|
||||
private fun getSplitOption(options: DecloptionsContext?): SplitWish {
|
||||
if(options==null)
|
||||
return SplitWish.DONTCARE
|
||||
private fun getSplitOption(tags: List<String>): SplitWish {
|
||||
return when {
|
||||
options.NOSPLIT().isNotEmpty() -> SplitWish.NOSPLIT
|
||||
options.SPLIT().isNotEmpty() -> SplitWish.SPLIT
|
||||
"@nosplit" in tags -> SplitWish.NOSPLIT
|
||||
"@split" in tags -> SplitWish.SPLIT
|
||||
else -> SplitWish.DONTCARE
|
||||
}
|
||||
}
|
||||
@ -773,16 +768,21 @@ private fun When_choiceContext.toAst(): WhenChoice {
|
||||
}
|
||||
|
||||
private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl {
|
||||
val options = decloptions()
|
||||
val zp = getZpOption(options)
|
||||
val split = getSplitOption(options)
|
||||
val tags = TAG().map { it.text }
|
||||
val validTags = arrayOf("@zp", "@requirezp", "@nozp", "@split", "@nosplit", "@shared", "@alignword", "@alignpage", "@align64", "@dirty")
|
||||
for(tag in tags) {
|
||||
if(tag !in validTags)
|
||||
throw SyntaxError("invalid variable tag '$tag'", toPosition())
|
||||
}
|
||||
val zp = getZpOption(tags)
|
||||
val split = getSplitOption(tags)
|
||||
val identifiers = identifier()
|
||||
val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME()
|
||||
val name = if(identifiers.size==1) identifiername.text else "<multiple>"
|
||||
val isArray = ARRAYSIG() != null || arrayindex() != null
|
||||
val alignword = options.ALIGNWORD().isNotEmpty()
|
||||
val align64 = options.ALIGN64().isNotEmpty()
|
||||
val alignpage = options.ALIGNPAGE().isNotEmpty()
|
||||
val alignword = "@alignword" in tags
|
||||
val align64 = "@align64" in tags
|
||||
val alignpage = "@alignpage" in tags
|
||||
if(alignpage && alignword)
|
||||
throw SyntaxError("choose a single alignment option", toPosition())
|
||||
val baseDt = datatype()?.toAst() ?: BaseDataType.UNDEFINED
|
||||
@ -800,9 +800,9 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
|
||||
idname.text
|
||||
},
|
||||
value,
|
||||
options.SHARED().isNotEmpty(),
|
||||
"@shared" in tags,
|
||||
if(alignword) 2u else if(align64) 64u else if(alignpage) 256u else 0u,
|
||||
options.DIRTY().isNotEmpty(),
|
||||
"@dirty" in tags,
|
||||
toPosition()
|
||||
)
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ TODO
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- SourceLineCache should be removed as a separate thing, it reloads all source files again and splits them by line. It should re-use the already loaded Sources. Wrap it all in a ImporterFileSystem?
|
||||
- Compiling Libraries: improve ability to create library files in prog8; for instance there's still stuff injected into the start of the start() routine AND there is separate setup logic going on before calling it.
|
||||
Make up our mind! Maybe all setup does need to be put into start() ? because the program cannot function correctly when the variables aren't initialized properly bss is not cleared etc. etc.
|
||||
Add a -library $xxxx command line option (and/or some directive) to preselect every setting that is required to make a library at $xxxx rather than a normal loadable and runnable program?
|
||||
|
@ -1,9 +1,4 @@
|
||||
%import compression
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
; compression.decode_rle(0,0,0)
|
||||
; compression.decode_zx0(0,0)
|
||||
compression.decode_tscrunch(0,0)
|
||||
}
|
||||
}
|
||||
|
@ -55,25 +55,7 @@ SINGLECHAR :
|
||||
'\'' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f'] ) '\''
|
||||
;
|
||||
|
||||
ZEROPAGE : '@zp' ;
|
||||
|
||||
ZEROPAGEREQUIRE : '@requirezp' ;
|
||||
|
||||
ZEROPAGENOT: '@nozp' ;
|
||||
|
||||
SHARED : '@shared' ;
|
||||
|
||||
SPLIT: '@split' ;
|
||||
|
||||
NOSPLIT: '@nosplit' ;
|
||||
|
||||
ALIGNWORD: '@alignword' ;
|
||||
|
||||
ALIGN64: '@align64' ;
|
||||
|
||||
ALIGNPAGE: '@alignpage' ;
|
||||
|
||||
DIRTY: '@dirty' ;
|
||||
TAG: '@' ('a'..'z' | '0'..'9')+ ;
|
||||
|
||||
ARRAYSIG : '[' [ \t]* ']' ;
|
||||
|
||||
@ -161,9 +143,7 @@ directive :
|
||||
|
||||
directivearg : stringliteral | identifier | integerliteral ;
|
||||
|
||||
vardecl: datatype (arrayindex | ARRAYSIG)? decloptions identifier (',' identifier)* ;
|
||||
|
||||
decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | ZEROPAGENOT | NOSPLIT | SPLIT | ALIGNWORD | ALIGN64 | ALIGNPAGE | DIRTY)* ;
|
||||
vardecl: datatype (arrayindex | ARRAYSIG)? TAG* identifier (',' identifier)* ;
|
||||
|
||||
varinitializer : vardecl '=' expression ;
|
||||
|
||||
@ -302,7 +282,7 @@ asmsubroutine :
|
||||
;
|
||||
|
||||
extsubroutine :
|
||||
'extsub' ('@bank' (constbank=integerliteral | varbank=scoped_identifier))? address=expression '=' asmsub_decl
|
||||
'extsub' (TAG (constbank=integerliteral | varbank=scoped_identifier))? address=expression '=' asmsub_decl
|
||||
;
|
||||
|
||||
asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns? ;
|
||||
|
Loading…
x
Reference in New Issue
Block a user