mirror of
https://github.com/irmen/prog8.git
synced 2025-11-05 17:21:42 +00:00
parser
This commit is contained in:
@@ -249,8 +249,12 @@ private fun Asmsub_paramsContext.toAst(): List<AsmSubroutineParameter> = asmsub_
|
|||||||
val identifiers = vardecl.identifier()
|
val identifiers = vardecl.identifier()
|
||||||
if(identifiers.size>1)
|
if(identifiers.size>1)
|
||||||
throw SyntaxError("parameter name must be singular", identifiers[0].toPosition())
|
throw SyntaxError("parameter name must be singular", identifiers[0].toPosition())
|
||||||
val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME()
|
val identifiername = identifiers.single().name()
|
||||||
AsmSubroutineParameter(identifiername.text, datatype, registerorpair, statusregister, toPosition())
|
AsmSubroutineParameter(identifiername, datatype, registerorpair, statusregister, toPosition())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IdentifierContext.name(): String {
|
||||||
|
return (this.UNICODEDNAME().text ?: this.UNDERSCORENAME()?.text)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseParamRegister(registerTok: Token?, pos: Position): Pair<RegisterOrPair?, Statusflag?> {
|
private fun parseParamRegister(registerTok: Token?, pos: Position): Pair<RegisterOrPair?, Statusflag?> {
|
||||||
@@ -289,7 +293,7 @@ private fun FunctioncallContext.toAst(): FunctionCallExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun InlineasmContext.toAst(): InlineAssembly {
|
private fun InlineasmContext.toAst(): InlineAssembly {
|
||||||
val type = directivename().NAME().text
|
val type = directivename().UNICODEDNAME().text
|
||||||
val isIR = when(type) {
|
val isIR = when(type) {
|
||||||
"asm" -> false
|
"asm" -> false
|
||||||
"ir" -> true
|
"ir" -> true
|
||||||
@@ -349,13 +353,13 @@ private fun Sub_paramsContext.toAst(): List<SubroutineParameter> =
|
|||||||
val identifiers = decl.identifier()
|
val identifiers = decl.identifier()
|
||||||
if(identifiers.size>1)
|
if(identifiers.size>1)
|
||||||
throw SyntaxError("parameter name must be singular", identifiers[0].toPosition())
|
throw SyntaxError("parameter name must be singular", identifiers[0].toPosition())
|
||||||
val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME()
|
val identifiername = identifiers.single().name()
|
||||||
|
|
||||||
val (registerorpair, statusregister) = parseParamRegister(it.register, it.toPosition())
|
val (registerorpair, statusregister) = parseParamRegister(it.register, it.toPosition())
|
||||||
if(statusregister!=null) {
|
if(statusregister!=null) {
|
||||||
throw SyntaxError("can't use status register as param for normal subroutines", Position(toPosition().file, it.register.line, it.register.charPositionInLine, it.register.charPositionInLine+1))
|
throw SyntaxError("can't use status register as param for normal subroutines", Position(toPosition().file, it.register.line, it.register.charPositionInLine, it.register.charPositionInLine+1))
|
||||||
}
|
}
|
||||||
SubroutineParameter(identifiername.text, datatype, zp, registerorpair, it.toPosition())
|
SubroutineParameter(identifiername, datatype, zp, registerorpair, it.toPosition())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getZpOption(tags: List<String>): ZeropageWish = when {
|
private fun getZpOption(tags: List<String>): ZeropageWish = when {
|
||||||
@@ -412,7 +416,7 @@ private fun Multi_assign_targetContext.toAst() : AssignTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun ClobberContext.toAst() : Set<CpuRegister> {
|
private fun ClobberContext.toAst() : Set<CpuRegister> {
|
||||||
val names = this.NAME().map { it.text }
|
val names = this.UNICODEDNAME().map { it.text }
|
||||||
try {
|
try {
|
||||||
return names.map { CpuRegister.valueOf(it) }.toSet()
|
return names.map { CpuRegister.valueOf(it) }.toSet()
|
||||||
} catch(_: IllegalArgumentException) {
|
} catch(_: IllegalArgumentException) {
|
||||||
@@ -470,7 +474,7 @@ private fun ArrayindexContext.toAst() : ArrayIndex =
|
|||||||
|
|
||||||
internal fun DirectiveContext.toAst() : Directive {
|
internal fun DirectiveContext.toAst() : Directive {
|
||||||
val pos= toPosition()
|
val pos= toPosition()
|
||||||
val position = Position(pos.file, pos.line, pos.startCol, directivename().NAME().symbol.stopIndex)
|
val position = Position(pos.file, pos.line, pos.startCol, directivename().UNICODEDNAME().symbol.stopIndex)
|
||||||
if(directivenamelist() != null) {
|
if(directivenamelist() != null) {
|
||||||
val identifiers = directivenamelist().scoped_identifier().map { DirectiveArg(it.text, null, it.toPosition()) }
|
val identifiers = directivenamelist().scoped_identifier().map { DirectiveArg(it.text, null, it.toPosition()) }
|
||||||
return Directive(directivename().text, identifiers, position)
|
return Directive(directivename().text, identifiers, position)
|
||||||
@@ -817,7 +821,7 @@ private fun When_choiceContext.toAst(): WhenChoice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun StructfielddeclContext.toAst(): Pair<DataType, String> {
|
private fun StructfielddeclContext.toAst(): Pair<DataType, String> {
|
||||||
val identifier = identifier().NAME().text
|
val identifier = identifier().UNICODEDNAME().text
|
||||||
val dt = datatype().toAst()
|
val dt = datatype().toAst()
|
||||||
return dt to identifier
|
return dt to identifier
|
||||||
}
|
}
|
||||||
@@ -832,8 +836,8 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
|
|||||||
val zp = getZpOption(tags)
|
val zp = getZpOption(tags)
|
||||||
val split = getSplitOption(tags)
|
val split = getSplitOption(tags)
|
||||||
val identifiers = identifier()
|
val identifiers = identifier()
|
||||||
val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME()
|
val identifiername = identifiers[0].name()
|
||||||
val name = if(identifiers.size==1) identifiername.text else "<multiple>"
|
val name = if(identifiers.size==1) identifiername else "<multiple>"
|
||||||
val isArray = ARRAYSIG() != null || arrayindex() != null
|
val isArray = ARRAYSIG() != null || arrayindex() != null
|
||||||
val alignword = "@alignword" in tags
|
val alignword = "@alignword" in tags
|
||||||
val align64 = "@align64" in tags
|
val align64 = "@align64" in tags
|
||||||
@@ -855,10 +859,7 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
|
|||||||
split,
|
split,
|
||||||
arrayindex()?.toAst(),
|
arrayindex()?.toAst(),
|
||||||
name,
|
name,
|
||||||
if(identifiers.size==1) emptyList() else identifiers.map {
|
if(identifiers.size==1) emptyList() else identifiers.map { it.name() },
|
||||||
val idname = it.NAME() ?: it.UNDERSCORENAME()
|
|
||||||
idname.text
|
|
||||||
},
|
|
||||||
value,
|
value,
|
||||||
"@shared" in tags,
|
"@shared" in tags,
|
||||||
if(alignword) 2u else if(align64) 64u else if(alignpage) 256u else 0u,
|
if(alignword) 2u else if(align64) 64u else if(alignpage) 256u else 0u,
|
||||||
|
|||||||
@@ -88,8 +88,10 @@ object InferredTypes {
|
|||||||
type.isPointer -> {
|
type.isPointer -> {
|
||||||
if(type.sub!=null)
|
if(type.sub!=null)
|
||||||
InferredType.known(DataType.pointer(type.sub!!))
|
InferredType.known(DataType.pointer(type.sub!!))
|
||||||
else
|
else if(type.subType!=null)
|
||||||
InferredType.known(DataType.pointerToType(type.subType!!))
|
InferredType.known(DataType.pointerToType(type.subType!!))
|
||||||
|
else
|
||||||
|
InferredType.known(DataType.pointerFromAntlr(type.subTypeFromAntlr!!))
|
||||||
}
|
}
|
||||||
type.isSplitWordArray -> {
|
type.isSplitWordArray -> {
|
||||||
when(type.sub) {
|
when(type.sub) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ STRUCTS and TYPED POINTERS
|
|||||||
Future Things and Ideas
|
Future Things and Ideas
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
|
||||||
- is "checkAssignmentCompatible" redundant (gets called just 1 time!) when we also have "checkValueTypeAndRange" ?
|
- is "checkAssignmentCompatible" redundant (gets called just 1 time!) when we also have "checkValueTypeAndRange" ?
|
||||||
- romable: should we have a way to explicitly set the memory address for the BSS area (instead of only the highram bank number on X16, allow a memory address too for the -varshigh option?)
|
- romable: should we have a way to explicitly set the memory address for the BSS area (instead of only the highram bank number on X16, allow a memory address too for the -varshigh option?)
|
||||||
- Kotlin: can we use inline value classes in certain spots?
|
- Kotlin: can we use inline value classes in certain spots?
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
struct Node {
|
struct Node {
|
||||||
bool flag
|
bool flag
|
||||||
|
^^Node next
|
||||||
}
|
}
|
||||||
|
|
||||||
^^Node ptr = 2000
|
^^Node ptr = 2000
|
||||||
@@ -14,7 +15,8 @@ main {
|
|||||||
txt.print_uw(ptr)
|
txt.print_uw(ptr)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
bool derp = ptr[10].flag
|
bool derp = ptr[2].flag
|
||||||
|
bool derp2 = ptr.next.next[2].flag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ BLOCK_COMMENT : '/*' ( BLOCK_COMMENT | . )*? '*/' -> skip ;
|
|||||||
WS : [ \t] -> skip ;
|
WS : [ \t] -> skip ;
|
||||||
// WS2 : '\\' EOL -> skip;
|
// WS2 : '\\' EOL -> skip;
|
||||||
VOID: 'void';
|
VOID: 'void';
|
||||||
NAME : [\p{Letter}][\p{Letter}\p{Mark}\p{Digit}_]* ; // match unicode properties
|
UNICODEDNAME : [\p{Letter}][\p{Letter}\p{Mark}\p{Digit}_]* ; // match unicode properties
|
||||||
UNDERSCORENAME : '_' NAME ; // match unicode properties
|
UNDERSCORENAME : '_' UNICODEDNAME ; // match unicode properties
|
||||||
DEC_INTEGER : DEC_DIGIT (DEC_DIGIT | '_')* ;
|
DEC_INTEGER : DEC_DIGIT (DEC_DIGIT | '_')* ;
|
||||||
HEX_INTEGER : '$' HEX_DIGIT (HEX_DIGIT | '_')* ;
|
HEX_INTEGER : '$' HEX_DIGIT (HEX_DIGIT | '_')* ;
|
||||||
BIN_INTEGER : '%' BIN_DIGIT (BIN_DIGIT | '_')* ;
|
BIN_INTEGER : '%' BIN_DIGIT (BIN_DIGIT | '_')* ;
|
||||||
@@ -145,7 +145,7 @@ unconditionaljump : 'goto' expression ;
|
|||||||
|
|
||||||
directive : directivename (directivenamelist | (directivearg? | directivearg (',' directivearg)*)) ;
|
directive : directivename (directivenamelist | (directivearg? | directivearg (',' directivearg)*)) ;
|
||||||
|
|
||||||
directivename: '%' NAME;
|
directivename: '%' UNICODEDNAME;
|
||||||
|
|
||||||
directivenamelist: '(' EOL? scoped_identifier (',' EOL? scoped_identifier)* ','? EOL?')' ;
|
directivenamelist: '(' EOL? scoped_identifier (',' EOL? scoped_identifier)* ','? EOL?')' ;
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ breakstmt : 'break';
|
|||||||
|
|
||||||
continuestmt: 'continue';
|
continuestmt: 'continue';
|
||||||
|
|
||||||
identifier : NAME | UNDERSCORENAME ;
|
identifier : UNICODEDNAME | UNDERSCORENAME ;
|
||||||
|
|
||||||
scoped_identifier : identifier ('.' identifier)* ;
|
scoped_identifier : identifier ('.' identifier)* ;
|
||||||
|
|
||||||
@@ -254,9 +254,9 @@ booleanliteral : 'true' | 'false' ;
|
|||||||
|
|
||||||
arrayliteral : '[' EOL? expression (',' EOL? expression)* ','? EOL? ']' ; // you can split the values over several lines, trailing comma allowed
|
arrayliteral : '[' EOL? expression (',' EOL? expression)* ','? EOL? ']' ; // you can split the values over several lines, trailing comma allowed
|
||||||
|
|
||||||
stringliteral : (encoding=NAME ':')? STRING ;
|
stringliteral : (encoding=UNICODEDNAME ':')? STRING ;
|
||||||
|
|
||||||
charliteral : (encoding=NAME ':')? SINGLECHAR ;
|
charliteral : (encoding=UNICODEDNAME ':')? SINGLECHAR ;
|
||||||
|
|
||||||
floatliteral : FLOAT_NUMBER ;
|
floatliteral : FLOAT_NUMBER ;
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ statement_block :
|
|||||||
|
|
||||||
sub_params : sub_param (',' EOL? sub_param)* ;
|
sub_params : sub_param (',' EOL? sub_param)* ;
|
||||||
|
|
||||||
sub_param: vardecl ('@' register=NAME)? ;
|
sub_param: vardecl ('@' register=UNICODEDNAME)? ;
|
||||||
|
|
||||||
asmsubroutine :
|
asmsubroutine :
|
||||||
inline? 'asmsub' asmsub_decl EOL? (statement_block EOL?)
|
inline? 'asmsub' asmsub_decl EOL? (statement_block EOL?)
|
||||||
@@ -303,15 +303,15 @@ asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns?
|
|||||||
|
|
||||||
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;
|
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;
|
||||||
|
|
||||||
asmsub_param : vardecl '@' register=NAME ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
asmsub_param : vardecl '@' register=UNICODEDNAME ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
||||||
|
|
||||||
asmsub_clobbers : 'clobbers' '(' clobber? ')' ;
|
asmsub_clobbers : 'clobbers' '(' clobber? ')' ;
|
||||||
|
|
||||||
clobber : NAME (',' NAME)* ; // A,X,Y allowed
|
clobber : UNICODEDNAME (',' UNICODEDNAME)* ; // A,X,Y allowed
|
||||||
|
|
||||||
asmsub_returns : '->' asmsub_return (',' EOL? asmsub_return)* ;
|
asmsub_returns : '->' asmsub_return (',' EOL? asmsub_return)* ;
|
||||||
|
|
||||||
asmsub_return : datatype '@' register=NAME ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
asmsub_return : datatype '@' register=UNICODEDNAME ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
||||||
|
|
||||||
|
|
||||||
if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? ; // statement is constrained later
|
if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? ; // statement is constrained later
|
||||||
|
|||||||
Reference in New Issue
Block a user