mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	parser
This commit is contained in:
		@@ -249,8 +249,12 @@ private fun Asmsub_paramsContext.toAst(): List<AsmSubroutineParameter> = asmsub_
 | 
			
		||||
    val identifiers = vardecl.identifier()
 | 
			
		||||
    if(identifiers.size>1)
 | 
			
		||||
        throw SyntaxError("parameter name must be singular", identifiers[0].toPosition())
 | 
			
		||||
    val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME()
 | 
			
		||||
    AsmSubroutineParameter(identifiername.text, datatype, registerorpair, statusregister, toPosition())
 | 
			
		||||
    val identifiername = identifiers.single().name()
 | 
			
		||||
    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?> {
 | 
			
		||||
@@ -289,7 +293,7 @@ private fun FunctioncallContext.toAst(): FunctionCallExpression {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private fun InlineasmContext.toAst(): InlineAssembly {
 | 
			
		||||
    val type = directivename().NAME().text
 | 
			
		||||
    val type = directivename().UNICODEDNAME().text
 | 
			
		||||
    val isIR = when(type) {
 | 
			
		||||
        "asm" -> false
 | 
			
		||||
        "ir" -> true
 | 
			
		||||
@@ -349,13 +353,13 @@ private fun Sub_paramsContext.toAst(): List<SubroutineParameter> =
 | 
			
		||||
            val identifiers = decl.identifier()
 | 
			
		||||
            if(identifiers.size>1)
 | 
			
		||||
                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())
 | 
			
		||||
            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))
 | 
			
		||||
            }
 | 
			
		||||
            SubroutineParameter(identifiername.text, datatype, zp, registerorpair, it.toPosition())
 | 
			
		||||
            SubroutineParameter(identifiername, datatype, zp, registerorpair, it.toPosition())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
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> {
 | 
			
		||||
    val names = this.NAME().map { it.text }
 | 
			
		||||
    val names = this.UNICODEDNAME().map { it.text }
 | 
			
		||||
    try {
 | 
			
		||||
        return names.map { CpuRegister.valueOf(it) }.toSet()
 | 
			
		||||
    } catch(_: IllegalArgumentException) {
 | 
			
		||||
@@ -470,7 +474,7 @@ private fun ArrayindexContext.toAst() : ArrayIndex =
 | 
			
		||||
 | 
			
		||||
internal fun DirectiveContext.toAst() : Directive {
 | 
			
		||||
    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) {
 | 
			
		||||
        val identifiers = directivenamelist().scoped_identifier().map { DirectiveArg(it.text, null, it.toPosition()) }
 | 
			
		||||
        return Directive(directivename().text, identifiers, position)
 | 
			
		||||
@@ -817,7 +821,7 @@ private fun When_choiceContext.toAst(): WhenChoice {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private fun StructfielddeclContext.toAst(): Pair<DataType, String> {
 | 
			
		||||
    val identifier = identifier().NAME().text
 | 
			
		||||
    val identifier = identifier().UNICODEDNAME().text
 | 
			
		||||
    val dt = datatype().toAst()
 | 
			
		||||
    return dt to identifier
 | 
			
		||||
}
 | 
			
		||||
@@ -832,8 +836,8 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
 | 
			
		||||
    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 identifiername = identifiers[0].name()
 | 
			
		||||
    val name = if(identifiers.size==1) identifiername else "<multiple>"
 | 
			
		||||
    val isArray = ARRAYSIG() != null || arrayindex() != null
 | 
			
		||||
    val alignword = "@alignword" in tags
 | 
			
		||||
    val align64 = "@align64" in tags
 | 
			
		||||
@@ -855,10 +859,7 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
 | 
			
		||||
            split,
 | 
			
		||||
            arrayindex()?.toAst(),
 | 
			
		||||
            name,
 | 
			
		||||
            if(identifiers.size==1) emptyList() else identifiers.map {
 | 
			
		||||
                val idname = it.NAME() ?: it.UNDERSCORENAME()
 | 
			
		||||
                idname.text
 | 
			
		||||
            },
 | 
			
		||||
            if(identifiers.size==1) emptyList() else identifiers.map { it.name() },
 | 
			
		||||
            value,
 | 
			
		||||
            "@shared" in tags,
 | 
			
		||||
            if(alignword) 2u else if(align64) 64u else if(alignpage) 256u else 0u,
 | 
			
		||||
 
 | 
			
		||||
@@ -88,8 +88,10 @@ object InferredTypes {
 | 
			
		||||
        type.isPointer -> {
 | 
			
		||||
            if(type.sub!=null)
 | 
			
		||||
                InferredType.known(DataType.pointer(type.sub!!))
 | 
			
		||||
            else
 | 
			
		||||
            else if(type.subType!=null)
 | 
			
		||||
                InferredType.known(DataType.pointerToType(type.subType!!))
 | 
			
		||||
            else
 | 
			
		||||
                InferredType.known(DataType.pointerFromAntlr(type.subTypeFromAntlr!!))
 | 
			
		||||
        }
 | 
			
		||||
        type.isSplitWordArray -> {
 | 
			
		||||
            when(type.sub) {
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@ STRUCTS and TYPED POINTERS
 | 
			
		||||
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" ?
 | 
			
		||||
- 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?
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ main {
 | 
			
		||||
    sub start() {
 | 
			
		||||
        struct Node {
 | 
			
		||||
            bool flag
 | 
			
		||||
            ^^Node next
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ^^Node ptr = 2000
 | 
			
		||||
@@ -14,7 +15,8 @@ main {
 | 
			
		||||
        txt.print_uw(ptr)
 | 
			
		||||
        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 ;
 | 
			
		||||
// WS2 : '\\' EOL -> skip;
 | 
			
		||||
VOID: 'void';
 | 
			
		||||
NAME :  [\p{Letter}][\p{Letter}\p{Mark}\p{Digit}_]* ;           // match unicode properties
 | 
			
		||||
UNDERSCORENAME :  '_' NAME ;           // match unicode properties
 | 
			
		||||
UNICODEDNAME :  [\p{Letter}][\p{Letter}\p{Mark}\p{Digit}_]* ;           // match unicode properties
 | 
			
		||||
UNDERSCORENAME :  '_' UNICODEDNAME ;           // match unicode properties
 | 
			
		||||
DEC_INTEGER :  DEC_DIGIT (DEC_DIGIT | '_')* ;
 | 
			
		||||
HEX_INTEGER :  '$' HEX_DIGIT (HEX_DIGIT | '_')* ;
 | 
			
		||||
BIN_INTEGER :  '%' BIN_DIGIT (BIN_DIGIT | '_')* ;
 | 
			
		||||
@@ -145,7 +145,7 @@ unconditionaljump :  'goto'  expression ;
 | 
			
		||||
 | 
			
		||||
directive : directivename (directivenamelist | (directivearg? | directivearg (',' directivearg)*))   ;
 | 
			
		||||
 | 
			
		||||
directivename: '%' NAME;
 | 
			
		||||
directivename: '%' UNICODEDNAME;
 | 
			
		||||
 | 
			
		||||
directivenamelist: '(' EOL? scoped_identifier (',' EOL? scoped_identifier)* ','? EOL?')' ;
 | 
			
		||||
 | 
			
		||||
@@ -244,7 +244,7 @@ breakstmt : 'break';
 | 
			
		||||
 | 
			
		||||
continuestmt: 'continue';
 | 
			
		||||
 | 
			
		||||
identifier :  NAME | UNDERSCORENAME ;
 | 
			
		||||
identifier :  UNICODEDNAME | UNDERSCORENAME ;
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
stringliteral : (encoding=NAME ':')? STRING ;
 | 
			
		||||
stringliteral : (encoding=UNICODEDNAME ':')? STRING ;
 | 
			
		||||
 | 
			
		||||
charliteral : (encoding=NAME ':')? SINGLECHAR ;
 | 
			
		||||
charliteral : (encoding=UNICODEDNAME ':')? SINGLECHAR ;
 | 
			
		||||
 | 
			
		||||
floatliteral :  FLOAT_NUMBER ;
 | 
			
		||||
 | 
			
		||||
@@ -289,7 +289,7 @@ statement_block :
 | 
			
		||||
 | 
			
		||||
sub_params :  sub_param (',' EOL? sub_param)* ;
 | 
			
		||||
 | 
			
		||||
sub_param: vardecl ('@' register=NAME)? ;
 | 
			
		||||
sub_param: vardecl ('@' register=UNICODEDNAME)? ;
 | 
			
		||||
 | 
			
		||||
asmsubroutine :
 | 
			
		||||
    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_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? ')' ;
 | 
			
		||||
 | 
			
		||||
clobber :  NAME (',' NAME)* ;       // A,X,Y allowed
 | 
			
		||||
clobber :  UNICODEDNAME (',' UNICODEDNAME)* ;       // A,X,Y allowed
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user