Project: expression-editor
Task (challenging): # Target
Use JavaScript to implement a `parse` function in `parser.js` and export `parse` with ESM named export.
You should implement `parse` based on existing `tokenize` function.

CAUTION: I want the file to be implemented with JavaScript but NOT TypeScript, and the filename should be `parser.js`.

# Technical Design Document
To complete the target, let's dig it deeper.

## `parse` function implemention detail

`parse` receive a `string` as input, and return `Program` as output.

### Constraints

#### Syntax Rules
- Identifier: A string composed of letters (a-z, A-Z), digits (0-9), and underscores, but it cannot start with a digit.
- LogicalExpression: Includes AND and OR. These operators are used to connect expressions and must be in uppercase.
- Parentheses: Used to change the order of operations or to group expressions, including left parenthesis ( and right parenthesis ).

#### Precedence and Associativity
- The AND and OR operators are left-associative, meaning they are evaluated from left to right in the absence of parentheses.
- The precedence of the AND operator is higher than that of OR.

### Node Types

I'll give you the TypeScript type definitions for your convenience.

```ts
type Program = {
  type: 'Program';
  children: SyntaxNode[];
}

type Identifier = {
  type: 'Identifier';
  name: string;
}

type LogicalExpression = {
  type: 'LogicalExpression';
  operator: 'AND' | 'OR';
  left: SyntaxNode;
  right: SyntaxNode;
}

type SyntaxNode = Identifier | LogicalExpression
```

### Examples

Besides these, here are some examples for you to better understand the AST structure.

<examples>
  <example source="" description="Empty source">
    ```js
    {
      type: 'Program',
      body: []
    }
    ```
  </example>

  <example source="foo" description="Single identifier">
    ```js
    {
      type: 'Program',
      body: [
        {
          type: 'Identifier',
          name: 'foo'
        }
      ]
    }
    ```
  </example>

  <example source="foo AND bar" description="Use AND with two identifiers">
    ```js
    {
      type: 'Program',
      body: [
        {
          type: 'LogicalExpression',
          operator: 'AND',
          left: {
            type: 'Identifier',
            name: 'foo'
          },
          right: {
            type: 'Identifier',
            name: 'bar'
          }
        }
      ]
    }
    ```
  </example>

  <example source="foo OR bar AND baz" description="Precedence of AND is higher than OR">
    ```js
    {
      type: 'Program',
      body: [
        {
          type: 'LogicalExpression',
          operator: 'OR',
          left: {
            type: 'Identifier',
            name: 'foo'
          },
          right: {
            type: 'LogicalExpression',
            operator: 'AND',
            left: {
              type: 'Identifier',
              name: 'bar'
            },
            right: {
              type: 'Identifier',
              name: 'baz'
            }
          }
        }
      ]
    }
    ```
  </example>

  <example source="foo OR bar OR baz" description="And/OR operators are both left associative">
    ```js
    {
      type: 'Program',
      body: [
        {
          type: 'LogicalExpression',
          operator: 'OR',
          left: {
            type: 'LogicalExpression',
            operator: 'OR',
            left: {
              type: 'Identifier',
              name: 'foo'
            },
            right: {
              type: 'Identifier',
              name: 'bar'
            }
          },
          right: {
            type: 'Identifier',
            name: 'baz'
          }
        }
      ]
    }
    ```
  </example>

  <example source="foo OR (bar OR baz)" description="Parentheses can change default associativity">
    ```js
    {
      type: 'Program',
      body: [
        {
          type: 'LogicalExpression',
          operator: 'OR',
          left: {
            type: 'Identifier',
            name: 'foo'
          },
          right: {
            type: 'LogicalExpression',
            operator: 'OR',
            left: {
              type: 'Identifier',
              name: 'bar'
            },
            right: {
              type: 'Identifier',
              name: 'baz'
            }
          }
        }
      ]
    }
    ```
  </example>

  <example source="  foo   OR     (   bar   OR   baz   )   " description="Any number of whitespaces are allowed, and does not affect the result">
    ```js
    {
      type: 'Program',
      body: [
        {
          type: 'LogicalExpression',
          operator: 'OR',
          left: {
            type: 'Identifier',
            name: 'foo'
          },
          right: {
            type: 'LogicalExpression',
            operator: 'OR',
            left: {
              type: 'Identifier',
              name: 'bar'
            },
            right: {
              type: 'Identifier',
              name: 'baz'
            }
          }
        }
      ]
    }
    ```
  </example>
</examples>