// File: /workspace/github_c_makefile_star2_O1/gregtour[P]minimal-compiler/grammar.c
// Function: LoadGrammar
int LoadGrammar(const char*    file,
                GRAMMAR_TABLE* table)
{
    FILE* input;
    char* buffer;
    int   size;
    int   i, r, start, end;
    int   rhs, symbol, token;
    int   read, line, col;

    // initialize table
    table->numSymbols = 0;
    table->symbols = (char*)malloc(SYMBOL_BUFFER_SIZE);
    table->symbols[SYMBOL_BUFFER_SIZE - 1] = 0;
    table->numTokens = 0;
    table->tokens = (char*)malloc(TOKEN_BUFFER_SIZE);
    table->tokens[TOKEN_BUFFER_SIZE - 1] = 0;
    table->numRules = 0;
    table->rules = 0;

    // add built in symbols
    gSymbolRoot       = 0;
    gSymbolGoal       = K_SYMBOL + table->numSymbols + 1;
    gSymbolEpsilon    = AddToken("<epsilon>", 9, table);
    gSymbolEOF        = AddToken("<$>", 3, table);
    gSymbolEndLine    = AddToken("<endl>", 6, table);
    gSymbolInteger    = AddToken("<integer>", 9, table);
    gSymbolFloat      = AddToken("<float>", 7, table);
    gSymbolString     = AddToken("<string>", 8, table);
    gSymbolIdentifier = AddToken("<identifier>", 12, table);

    // read grammar file
    printf("Loading context free grammar from %s...\n", file);
    input = fopen(file, "rb");
    if (input == 0) {
        printf("Could not open grammar file.\n");
        return 1;
    }
    fseek(input, 0, SEEK_END);
    size = ftell(input);
    rewind(input);
    buffer = (char*)malloc(size+2);
    read = fread(buffer, 1, size, input);
    buffer[size] = '\n';
    buffer[size+1] = 0;
    fclose(input);
    
    printf("Read %i of %i bytes.\n", read, size);

    if (size == 0) {
        printf("Unable to read grammar rules.\n");
        return 1;
    }

    // count rules
    table->numRules = 0; col = 0;
    for (i = 0; i < size; i++)
    {
        // don't count comments or new lines
        if (col == 0 &&
            (buffer[i] == ';' || buffer[i] == '\r' || buffer[i] == '\n'))
        {
            while (i < size && buffer[i] != '\n')
                i++;
            continue;
        }
        col++;
        if (buffer[i] == '\r') buffer[i] = 0;
        else if (buffer[i] == '\n') { table->numRules++; col = 0; }
    }
    printf("Loaded %i grammar rules.\n", table->numRules);
    table->numRules++;

    // S' -> S
    table->rules = (RULE*)malloc(sizeof(RULE) * table->numRules);
    table->rules[0].lhs = gSymbolRoot;
    table->rules[0].rhs = (int*)malloc(sizeof(int) * RULE_RHS_SIZE);
    table->rules[0].rhs[0] = gSymbolGoal;
    table->rules[0].rhs[1] = 0;
    table->rules[0].rhsLength = 1;

    // parse rules
    start = 0; end = 0; line = 0;
    for (r = 1; r < table->numRules; r++)
    {
        // skip comments or blank lines
        while (start < size &&
                (buffer[start] == ';' || buffer[start] == '\n'
                 || buffer[start] == 0))
        {
            while (start < symbol && buffer[start] != '\n')
                start++;
            start++;
            line++;
        }
        // left hand symbol
        while (start < size && buffer[start] != '<')
            start++;
        end = start;
        while (start < size && buffer[end] != '>')
            end++;
        symbol = AddSymbol(&buffer[start], end - start + 1, table);
        if (symbol == 0) {
            printf("Could not identify left hand symbol in rule %i ", r+1);
            printf("on line %i.\n", line);
            return 1;
        }
        table->rules[r].lhs = symbol;
        start = end + 1;

        // ::= operator
        while (start < size - 2)
        {
            if (buffer[start] == ':' &&
                buffer[start+1] == ':' &&
                buffer[start+2] == '=')
            {
                break;
            }
            start++;
        }
        start = start + 3;

        // right hand side
        table->rules[r].rhs = (int*)malloc(sizeof(int) * RULE_RHS_SIZE);
        rhs = 0;
        while (start < size &&
               buffer[start] != '\n' &&
               buffer[start] != 0 &&
               rhs < RULE_RHS_SIZE)
        {
            if (buffer[start] == '<')
            {
                // symbol
                end = start;
                while (buffer[end] != '>' &&
                       end < size)
                {
                    end++;
                }

                symbol = FindToken(&buffer[start], end - start + 1, *table);
                if (symbol == 0)
                    symbol = AddSymbol(&buffer[start], end - start + 1, table);
                if (symbol == 0)
                {
                    printf("Could not identify right hand symbol in rule %i ", r+1);
                    printf("on line %i.\n", line);
                    return 1;
                }
                table->rules[r].rhs[rhs] = symbol;
                rhs++;
                start = end + 1;
            }
            else if (buffer[start] != ' ')
            {
                // token
                end = start;
                while (buffer[end] != ' ' &&
                      (buffer[end] != '<' ||
                       buffer[end-1] == '\\') &&
                       buffer[end] != '\n' &&
                       buffer[end] != 0 &&
                       end < size)
                {
                    end++;
                }

                token = AddToken(&buffer[start], end - start, table);
                if (token == 0)
                {
                    printf("Could not identify right hand token in rule %i ", r+1);
                    printf("on line %i.\n", line);
                    return 1;
                }
                table->rules[r].rhs[rhs] = token;
                rhs++;
                start = end;
            }
            else
            {
                // whitespace
                start++;
            }
        }
        table->rules[r].rhs[rhs] = 0;
        table->rules[r].rhsLength = rhs;
        if (rhs == 0) {
            printf("Rule %i on line %i has no right hand side.\n", r, line);
            return 1;
        } else if (rhs == RULE_RHS_SIZE) {
            printf("Rule %i on line %i may be too long.\n", r, line);
        }
    }

    if (gSymbolGoal == 0)
    {
        printf("Grammar is missing a goal symbol.\n");
        return 1;
    }

    printf("Parsed %i of %i rules.\n\n", r, table->numRules);

    free(buffer);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rsi, %r15
movq %rdi, %rbx
xorl %r14d, %r14d
movl %r14d, (%rsi)
movl $0x1000, %edi           # imm = 0x1000
callq 0x2100
movq %rax, 0x8(%r15)
movb %r14b, 0xfff(%rax)
movl %r14d, 0x10(%r15)
movl $0x1000, %edi           # imm = 0x1000
callq 0x2100
movq %rax, 0x18(%r15)
movb %r14b, 0xfff(%rax)
movl %r14d, 0x20(%r15)
movq $0x0, 0x28(%r15)
movl %r14d, 0x160c7(%rip)    # 0x192f8
movl $0x1001, %eax           # imm = 0x1001
addl (%r15), %eax
movl %eax, 0x8e71(%rip)      # 0xc0b0
leaq 0x4f97(%rip), %rdi      # 0x81dd
movl $0x9, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8e5b(%rip)      # 0xc0b4
leaq 0x4f87(%rip), %rdi      # 0x81e7
movl $0x3, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8e45(%rip)      # 0xc0b8
leaq 0x4f71(%rip), %rdi      # 0x81eb
movl $0x6, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8e2f(%rip)      # 0xc0bc
leaq 0x4f5e(%rip), %rdi      # 0x81f2
movl $0x9, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8e19(%rip)      # 0xc0c0
leaq 0x4f4e(%rip), %rdi      # 0x81fc
movl $0x7, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8e03(%rip)      # 0xc0c4
leaq 0x4f3c(%rip), %rdi      # 0x8204
movl $0x8, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8ded(%rip)      # 0xc0c8
leaq 0x4f2b(%rip), %rdi      # 0x820d
movl $0xc, %esi
movq %r15, %rdx
callq 0x2f88
movl %eax, 0x8dd7(%rip)      # 0xc0cc
leaq 0x4f1e(%rip), %rdi      # 0x821a
movq %rbx, %rsi
xorl %eax, %eax
callq 0x2090
leaq 0x4e35(%rip), %rsi      # 0x8142
movq %rbx, %rdi
callq 0x2120
testq %rax, %rax
je 0x3866
movq %rax, %rbx
movq %r15, -0x38(%rbp)
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x2110
movq %rbx, %rdi
callq 0x20f0
movq %rax, %r12
movq %rbx, %rdi
callq 0x20a0
movq %r12, %r15
shlq $0x20, %r15
movabsq $0x200000000, %rdi      # imm = 0x200000000
addq %r15, %rdi
sarq $0x20, %rdi
callq 0x2100
movq %rax, %r14
movq %r12, -0x48(%rbp)
movslq %r12d, %r12
movl $0x1, %esi
movq %rax, %rdi
movq %r12, %rdx
movq %rbx, %rcx
callq 0x2060
movq %rax, %r13
movb $0xa, (%r14,%r12)
movabsq $0x100000000, %rax      # imm = 0x100000000
addq %r15, %rax
sarq $0x20, %rax
movb $0x0, (%r14,%rax)
movq %rbx, %rdi
callq 0x2070
leaq 0x4e95(%rip), %rdi      # 0x8243
movl %r13d, %esi
movl %r12d, %edx
xorl %eax, %eax
callq 0x2090
testl %r12d, %r12d
je 0x386f
movq -0x38(%rbp), %r12
movl $0x0, 0x20(%r12)
movq -0x48(%rbp), %r10
jle 0x345c
movl %r10d, %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
xorl %edx, %edx
movabsq $0x800000000002400, %rcx # imm = 0x800000000002400
xorl %esi, %esi
movslq %esi, %rdi
testl %edx, %edx
je 0x3412
movzbl (%r14,%rdi), %r8d
cmpl $0xa, %r8d
je 0x344a
incl %edx
cmpl $0xd, %r8d
jne 0x3455
movb $0x0, (%r14,%rdi)
jmp 0x3455
movzbl (%r14,%rdi), %r8d
cmpq $0x3b, %r8
ja 0x33f8
btq %r8, %rcx
jae 0x33f8
xorl %edx, %edx
cmpl %r10d, %esi
jge 0x3455
leaq (%r14,%rdi), %r8
movq %rax, %r9
subq %rdi, %r9
xorl %edi, %edi
cmpb $0xa, (%r8,%rdi)
je 0x3453
incq %rdi
cmpq %rdi, %r9
jne 0x3436
movl %r10d, %esi
jmp 0x3455
incl 0x20(%r12)
xorl %edx, %edx
jmp 0x3455
addl %edi, %esi
incl %esi
cmpl %r10d, %esi
jl 0x33f1
movl 0x20(%r12), %esi
leaq 0x4df1(%rip), %rdi      # 0x8259
xorl %eax, %eax
callq 0x2090
movslq 0x20(%r12), %rdi
incq %rdi
movl %edi, 0x20(%r12)
shlq $0x4, %rdi
callq 0x2100
movq %rax, %rbx
movq %rax, 0x28(%r12)
movl 0x15e65(%rip), %eax     # 0x192f8
movl %eax, (%rbx)
movl $0x60, %edi
callq 0x2100
movq %rax, 0x8(%rbx)
movl 0x8c07(%rip), %ecx      # 0xc0b0
movl %ecx, (%rax)
movl $0x0, 0x4(%rax)
movl $0x1, 0x4(%rbx)
movl 0x20(%r12), %edx
movl $0x1, %esi
cmpl $0x2, %edx
jl 0x3843
movq -0x48(%rbp), %r11
leal -0x2(%r11), %eax
movslq %r11d, %r15
movl %eax, -0x60(%rbp)
cltq
movq %rax, -0x68(%rbp)
leal -0x3(%r11), %eax
movl %eax, -0x5c(%rbp)
leaq -0x1(%r15), %r8
movl $0x1, %esi
movabsq $0x800000000000401, %r9 # imm = 0x800000000000401
xorl %r13d, %r13d
xorl %ebx, %ebx
movq %r8, -0x70(%rbp)
movq %rsi, -0x40(%rbp)
cmpl %r11d, %ebx
jge 0x3553
movslq %r10d, %rax
movslq %ebx, %rdx
movzbl (%r14,%rdx), %ecx
cmpq $0x3b, %rcx
ja 0x3553
btq %rcx, %r9
jae 0x3553
cmpl %r10d, %ebx
jge 0x3549
leaq (%r14,%rdx), %rcx
movq %rax, %rsi
subq %rdx, %rsi
xorl %edx, %edx
cmpb $0xa, (%rcx,%rdx)
je 0x3547
incq %rdx
cmpq %rdx, %rsi
jne 0x3534
movl %r10d, %ebx
jmp 0x3549
addl %edx, %ebx
incl %ebx
incl %r13d
cmpl %r11d, %ebx
jl 0x350f
cmpl %r11d, %ebx
setl %al
jge 0x3586
movslq %ebx, %rcx
cmpb $0x3c, (%r14,%rcx)
je 0x3586
cmpq %rcx, %r8
je 0x3581
leaq 0x1(%rcx), %rbx
cmpb $0x3c, 0x1(%r14,%rcx)
movq %rbx, %rcx
jne 0x3565
cmpq %r15, %rbx
setl %al
jmp 0x3586
xorl %eax, %eax
movl %r11d, %ebx
movslq %ebx, %rcx
testb %al, %al
je 0x359e
movq %rcx, %rbx
cmpb $0x3e, (%r14,%rbx)
je 0x359e
incq %rbx
testb %al, %al
jne 0x3590
leaq (%r14,%rcx), %rdi
movl %ebx, %esi
subl %ecx, %esi
incl %esi
movq %r12, %rdx
callq 0x2e6b
testl %eax, %eax
je 0x38b8
movq 0x28(%r12), %r9
movq -0x40(%rbp), %rcx
shlq $0x4, %rcx
movq %rcx, -0x58(%rbp)
movl %eax, (%r9,%rcx)
movslq %ebx, %rdx
incq %rdx
cmpl -0x60(%rbp), %edx
movl %eax, -0x30(%rbp)
movq %r9, -0x50(%rbp)
jge 0x361d
movl %ebx, %r8d
leaq (%r14,%rdx), %rcx
movq -0x68(%rbp), %rsi
subq %rdx, %rsi
xorl %edx, %edx
cmpb $0x3a, (%rcx,%rdx)
jne 0x360c
leaq (%r8,%rdx), %rdi
movslq %edi, %rdi
cmpb $0x3a, 0x2(%r14,%rdi)
jne 0x360c
cmpb $0x3d, 0x3(%r14,%rdi)
je 0x361b
incq %rdx
cmpq %rdx, %rsi
jne 0x35ef
movl -0x5c(%rbp), %eax
movl %eax, %ebx
jmp 0x361d
addl %edx, %ebx
movl %ebx, %r12d
addl $0x4, %r12d
movl $0x60, %edi
callq 0x2100
movq -0x58(%rbp), %rcx
movq -0x50(%rbp), %rdx
movq %rax, 0x8(%rdx,%rcx)
xorl %r8d, %r8d
movq -0x48(%rbp), %r11
cmpl %r11d, %r12d
jge 0x37ba
xorl %r8d, %r8d
movl -0x30(%rbp), %r10d
movslq %r12d, %rax
movzbl (%r14,%rax), %ecx
cmpl $0xa, %ecx
je 0x37c3
testl %ecx, %ecx
je 0x37c3
cmpl $0x17, %r8d
jg 0x37c3
cmpl $0x20, %ecx
je 0x3715
leaq (%r14,%rax), %rdi
cmpl $0x3c, %ecx
movl %r8d, -0x50(%rbp)
jne 0x3720
xorl %ebx, %ebx
incl %ebx
cmpq %r15, %rax
jge 0x36a3
cmpb $0x3e, (%r14,%rax)
leaq 0x1(%rax), %rax
jne 0x3691
movq -0x38(%rbp), %rax
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movups %xmm2, 0x20(%rsp)
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl %ebx, %esi
movq %rdi, -0x30(%rbp)
callq 0x30cd
movl %eax, %r10d
testl %eax, %eax
jne 0x36e4
movq -0x30(%rbp), %rdi
movl %ebx, %esi
movq -0x38(%rbp), %rdx
callq 0x2e6b
movl %eax, %r10d
testl %r10d, %r10d
movq -0x48(%rbp), %r11
je 0x389a
movq -0x38(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x58(%rbp), %rcx
movq 0x8(%rax,%rcx), %rax
movl -0x50(%rbp), %r8d
movslq %r8d, %rcx
movl %r10d, (%rax,%rcx,4)
incl %r8d
addl %ebx, %r12d
jmp 0x3718
incl %r12d
movl %r12d, %ebx
jmp 0x37ac
cmpl %r11d, %r12d
movl %r11d, %ecx
cmovgl %r12d, %ecx
decq %rax
movl %r12d, %ebx
movl %r10d, -0x30(%rbp)
movzbl 0x1(%r14,%rax), %edx
cmpl $0x3b, %edx
jle 0x3756
cmpl $0x3c, %edx
jne 0x3764
cmpb $0x5c, (%r14,%rax)
jne 0x3770
testl %edx, %edx
je 0x3770
cmpl $0xa, %edx
jne 0x3764
jmp 0x3770
testl %edx, %edx
je 0x3770
cmpl $0xa, %edx
je 0x3770
cmpl $0x20, %edx
je 0x3770
incl %ebx
incq %rax
cmpq %r15, %rax
jl 0x3734
movl %ecx, %ebx
movl %ebx, %esi
subl %r12d, %esi
movq -0x38(%rbp), %r12
movq %r12, %rdx
callq 0x2f88
testl %eax, %eax
je 0x38a9
movq 0x28(%r12), %rcx
movq -0x58(%rbp), %rdx
movq 0x8(%rcx,%rdx), %rcx
movl -0x50(%rbp), %r8d
movslq %r8d, %rdx
movl %eax, (%rcx,%rdx,4)
incl %r8d
movq -0x48(%rbp), %r11
movl -0x30(%rbp), %r10d
movl %ebx, %r12d
cmpl %r11d, %ebx
jl 0x3652
jmp 0x37c6
movl %r12d, %ebx
movl -0x30(%rbp), %r10d
jmp 0x37c6
movl %r12d, %ebx
movq -0x38(%rbp), %r12
movq 0x28(%r12), %rax
movq -0x58(%rbp), %rsi
movq 0x8(%rax,%rsi), %rcx
movslq %r8d, %rdx
movl $0x0, (%rcx,%rdx,4)
movl %edx, 0x4(%rax,%rsi)
cmpl $0x18, %edx
je 0x37f9
testl %r8d, %r8d
movq -0x40(%rbp), %rsi
jne 0x3824
jmp 0x38df
leaq 0x4b3d(%rip), %rdi      # 0x833d
movq -0x40(%rbp), %r12
movl %r12d, %esi
movl %r13d, %edx
xorl %eax, %eax
movl %r10d, -0x30(%rbp)
callq 0x2090
movl -0x30(%rbp), %r10d
movq %r12, %rsi
movq -0x38(%rbp), %r12
movq -0x48(%rbp), %r11
incq %rsi
movslq 0x20(%r12), %rdx
cmpq %rdx, %rsi
movq -0x70(%rbp), %r8
movabsq $0x800000000000401, %r9 # imm = 0x800000000000401
jl 0x3503
cmpl $0x0, 0x8866(%rip)      # 0xc0b0
je 0x3878
leaq 0x4b0f(%rip), %rdi      # 0x8362
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x2090
movq %r14, %rdi
callq 0x2030
jmp 0x3889
leaq 0x4b65(%rip), %rdi      # 0x83d2
jmp 0x387f
leaq 0x4b3e(%rip), %rdi      # 0x83b4
jmp 0x387f
leaq 0x4b13(%rip), %rdi      # 0x8392
callq 0x2050
movl $0x1, %ebx
movl %ebx, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq -0x40(%rbp), %rsi
incl %esi
leaq 0x4a09(%rip), %rdi      # 0x82b0
jmp 0x38c5
movq -0x40(%rbp), %rsi
incl %esi
leaq 0x4a2b(%rip), %rdi      # 0x82e1
jmp 0x38c5
movq -0x40(%rbp), %rsi
incl %esi
leaq 0x49ae(%rip), %rdi      # 0x8273
xorl %eax, %eax
callq 0x2090
leaq 0x49d0(%rip), %rdi      # 0x82a3
movl %r13d, %esi
xorl %eax, %eax
callq 0x2090
jmp 0x3884
leaq 0x4a2b(%rip), %rdi      # 0x8311
movl %r13d, %edx
xorl %eax, %eax
callq 0x2090
jmp 0x3884