notice something strange about the script engine:

1. Command is executed as soon as it's parsed, myabe we should wait until the
whole file is analysed.

2. Menu entry is parsed twice.

3. Memory consumption is huge, each token would take up 2048/2096 bytes. Maybe
we should allocate just enough memory to hold the string.

4. Some problem with syntax
For example,

if ls; then ls fi

works (shouldn't be), but

if ls; then ls; fi

doesn't (should be), and

if ls; then
  ls
fi

result in an infinite loop.

I'm thinking about a new architecture. The script can be represented using
binary tree. Every node in the tree has two pointers. Child points to the first
node in the next level, while next points to the next node in the same level.
With this design, when we want to free a certain node, just free its entire
child branch. there is no need to record memory usage anymore.

Here is a sample syntax file.

line: one_line_commands
      {
        $$=$1;
      }
      | function_cmd
      {
        $$=$1;
      }
      | menu_cmd
      {
        $$=$1;
      }

newlines:
          | newlines "\n"

commands: one_line_commands
          {
            $$=$1;
          }
          | one_line_commands "\n" newlines commands
          {
            $$=$1;
            append_items($$, $2);
          }

one_line_commands: command
                {
                  $$=$1;
                  $1->next=0;
                }
                | command ; one_line_commands
                {
                  $$=$1;
                  $1->next=$2;
                }

command: simple_command
         {
           $$=$1;
         }
         | if_command
         {
           $$=$1;
         }


simple_command: text arguments
                {
                   $$->type=SIMPLE_COMMAND;
                   $$->child=$1;
                }

arguments:
          {
            $$=0;
          }
         | text arguments
          {
            $$=$1;
            $1->next=$2;
          }

if_cmdblk: command ;
             {
               $$->type=COMMAND_LIST;
               $$->child=$1;
               $1->next=0;
             }
             || "\n" newlines commands "\n" newlines
             {
               $$->type=COMMAND_LIST;
               $$->child=$2;
             }


if_command: "if" simple_command ; "then" if_cmdblk "fi"
          {
            $$->type=IF_COMMAND;
            $$->child=$2;
            $2->next=$5;
            $5->next=0;
          }
          | "if" simple_command ; "then" if_cmdblk "else" if_cmdblk "fi"
          {
            $$->type=IF_COMMAND;
            $$->child=$2;
            $2->next=$5;
            $5->next=$7;
            $7->next=0;
          }

function_cmd: "function" text newlines "{" newlines commands newlines "}"
              {
                $$->type=FUNCTION_CMD;
                $$->child=$2;
                $2->next->type=COMMAND_LIST;
                $2->next->child=$6;
              }

menu_cmd: "menuentry" text newlines "{" newlines commands newlines "}"
              {
                $$->type=MENU_CMD;
                $$->child=$2;
                $2->next->type=COMMAND_LIST;
                $2->next->child=$6;
              }

Text is the basic token, it can be plain text or text mixed with variable, for
example:

abc
"aa bb"
"aa"bb
aa$BB
aa${BB}cc
...

The lexer would break it into pieces.

abc => abc
"aa bb" => "aa bb"
"aa"bb => "aa" bb
aa$BB => aa $BB
aa${BB}cc => aa $BB cc

When text is evaluated, each piece is evaluated individually, then joined
together to form the end result.

-- 
Bean



_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to