Implement the named labels for assembly Let's assume we've got an imaginary assembler. The assembler supports numerical labels. An infinite loop example:

:1
    jmp 1


Your task is, to write a preprocessor for this assembler supporting named labels (instead of numerical ones; with up to 8 characters in length), so the label name is replaced to it's numerical value.

The assembler uses a dot (.) to express a character constant, for example:

mov dl, .A


Will store ASCII(65) - 'A', in the register dl. The assembler supports string constants in double quotes too:

:20
db "Hello, world!"


So, to sum things up, you need to be aware of character constants, and the fact that you can't perform any substitution inside quote-enclosed strings.

The label declaration character and reference character is up to your choice, but for the sake of completness I will use a $ to refer to a label, and @ to denote a label.

The label' number might be any natural number not equal to zero.

You may assume that assembly on the input is perfectly valid.

Let's look at a few examples:

@loop
    jmp $loop


:1
    jmp 1




jmp $skip
mov dl, .@
@skip
cmp dl, .$


jmp 1
mov dl, .@
:1
cmp dl, .$




@x
db "$a @b"
@a
    jmp $a
    @b
        jmp $b


:1
db "$a @b"
:2
    jmp 2
    :3
        jmp 3


This is a code golf, so the smallest answer wins. Standard rules and loopholes apply.

You can safetly assume that the user won't use numerical labels anymore, and the labels contain just A-Za-z letters.

Label declaration and reference character has to be different.
JavaScript (ES6), 96 bytes
Uses @label for a declaration and %label for a reference.

s=&gt;s.replace(o=/^\s*@(.+)/gm,(_,s)=&gt;':'+(o[s]=++n),n=0).replace(/&quot;.*?&quot;|%(\w+)/g,(s,x)=&gt;x?o[x]:s)

Try it online!
Commented
(alternate slash characters are used below to prevent the SE syntax highligter from going mad)
s =&gt;                  // s = input string
  s.replace(          // 1st pass:
    o =               //   assign the regex object to o; we'll use it to store the labels
    ∕^\s*@(.+)∕gm,    //   look for [start] + [optional whitespace] + '@' + [label]
    (_, s) =&gt;         //   replace with:
      ':' +           //     ':' + label ID
      (o[s] = ++n),   //     increment n and store the label in o
    n = 0             //   start with n = 0
  )                   // end of replace()
  .replace(           // 2nd pass:
    ∕&quot;.*?&quot;|%(\w+)∕g,  //   look for either &quot;.*?&quot; (non-greedily) or %label
    (s, x) =&gt;         //   replace with:
      x ? o[x]        //     o[label] if x is defined,
        : s           //     or the original string otherwise
  )                   // end of replace()