protected void computeFirsts() {
		boolean changed = true;
		while (changed) {
			changed = false;
			// [A] => 'a' ALPHA implies 'a' in First[A]
			// [A] => ALPHA [X] BETA  implies First[A] includes First[X] and First(ALPHA)
			// Walk each production from the left over nullable non-terminals
			// Add the first of all each symbol
			// Terminate after a terminal or non-nullable symbol
			for (AbstractAssemblyProduction<?> prod : grammar) {
				for (AssemblySymbol sym : prod.getRHS()) {
					if (sym instanceof AssemblyNonTerminal) {
						AssemblyNonTerminal nt = (AssemblyNonTerminal) sym;
						changed |= first.putAll(prod.getLHS(), first.get(nt));
						if (!nullable.contains(sym)) {
							break; // next production
						}
					}
					else if (sym instanceof AssemblyTerminal) {
						AssemblyTerminal t = (AssemblyTerminal) sym;
						changed |= first.put(prod.getLHS(), t);
						break; // next production
					}
				}
			}
		}
	}
Compute the first set for each non-terminal
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/parse/AssemblyFirstFollow.java