Changeset 13 for trunk/UKConfig.pas


Ignore:
Timestamp:
May 9, 2014, 12:37:10 AM (10 years ago)
Author:
chronos
Message:
  • Added: Basic parsing of "Depends on" expressions.
Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

    • Property svn:ignore
      •  

        old new  
        33LinuxBuilder.lps
        44LinuxBuilder.res
         5backup
  • trunk/UKConfig.pas

    r11 r13  
    1515    vtComment);
    1616
     17  TMenuNode = class;
    1718  TLoadTreeOption = (toShowSystem);
    1819  TLoadTreeOptions = set of TLoadTreeOption;
     
    3031    ExpOperator: TExpOperator;
    3132    Items: TObjectList; // TList<TExpression>
    32     constructor Create;
     33    Parent: TExpression;
     34    function Show: String; virtual;
     35    procedure GetList(List: TStringList); virtual;
     36    constructor Create; virtual;
    3337    destructor Destroy; override;
    3438  end;
    3539
    36   TExpressionVar = class
     40  TCompareType = (ctNone, ctEqual, ctNotEqual);
     41
     42  { TExpressionVar }
     43
     44  TExpressionVar = class(TExpression)
    3745    Name: string;
     46    Node: TMenuNode;
    3847    Negative: Boolean;
     48    Compare: TCompareType;
     49    Value: string;
     50    constructor Create; override;
     51    procedure GetList(List: TStringList); override;
     52    function Show: String; override;
    3953  end;
    4054
     
    4256
    4357  TMenuNode = class
     58  private
     59    function GetVisible: Boolean;
     60  public
    4461    ID: string;
    4562    Name: string;
    46     Depends: TStringList;
     63    DependsOn: TExpression;
    4764    Selects: TStringList;
    4865    Description: TStringList;
     
    7087    function GetTopNode: TMenuNode; virtual;
    7188    function FindNode(ID: string): TMenuNode; virtual;
     89    property Visible: Boolean read GetVisible;
    7290  end;
    7391
     
    82100    Arch: string;
    83101    FOnLog: TOnLogEvent;
     102    ParseFileName: string;
     103    LineNumber: Integer;
    84104    function GetTopCondition: string;
    85105    procedure Log(Text: string);
    86106    function IsWhiteSpace(Character: Char): Boolean;
     107    function IsAlpha(Character: Char): Boolean;
     108    function IsAlphaNumeric(Character: Char): Boolean;
     109    function IsNumeric(Character: Char): Boolean;
     110    function IsIdentifier(Name: string): Boolean;
     111    function IsSpecialSymbol(Character: Char): Boolean;
     112    procedure Expect(var Text: string; Token: string);
    87113    function GetNextToken(var Text: string): string;
     114    procedure ParseExpression(Node: TMenuNode; Line: string);
    88115    procedure ParseFile(FileName: string);
    89116    procedure ParseConfig;
    90117    procedure ParseMakeFile;
     118    function GetLog: string;
    91119  public
    92120    TopNode: TMenuNode;
     
    105133implementation
    106134
     135{ TExpressionVar }
     136
     137constructor TExpressionVar.Create;
     138begin
     139  inherited;
     140  Compare := ctNone;
     141  Value := '';
     142  Negative := False;
     143  Name := '';
     144end;
     145
     146procedure TExpressionVar.GetList(List: TStringList);
     147begin
     148  inherited GetList(List);
     149  List.Add(Name);
     150end;
     151
     152function TExpressionVar.Show: String;
     153begin
     154  Result := Name;
     155  if Negative then Result := '!' + Result;
     156  if Compare = ctEqual then Result := Result + ' = ' + Value;
     157  if Compare = ctNotEqual then Result := Result + ' != ' + Value;
     158end;
     159
    107160{ TExpression }
    108161
     162function TExpression.Show: String;
     163var
     164  Operand: string;
     165  I: Integer;
     166begin
     167  Result := '';
     168  if ExpOperator = eoAnd then Operand := '&&';
     169  if ExpOperator = eoOr then Operand := '||';
     170  for I := 0 to Items.Count - 1 do begin
     171    Result := Result + TExpression(Items[I]).Show;
     172    if I < (Items.Count - 1) then Result := Result + ' ' + Operand + ' ';
     173  end;
     174  if Assigned(Parent) then Result := '(' + Result + ')';
     175end;
     176
     177procedure TExpression.GetList(List: TStringList);
     178var
     179  I: Integer;
     180begin
     181  for I := 0 to Items.Count - 1 do
     182    TExpression(Items[I]).GetList(List);
     183end;
     184
    109185constructor TExpression.Create;
    110186begin
    111187  Items := TObjectList.Create;
     188  Parent := nil;
     189  ExpOperator := eoAnd;
    112190end;
    113191
     
    119197
    120198{ TMenuNode }
     199
     200function TMenuNode.GetVisible: Boolean;
     201var
     202  I: Integer;
     203begin
     204  Result := True;
     205  //for I := 0 to Depends.Count - 1 do
     206  //if Depends[I]
     207end;
    121208
    122209constructor TMenuNode.Create;
     
    125212  ID := '';
    126213  Parent := nil;
    127   Depends := TStringList.Create;
     214  DependsOn := TExpression.Create;
    128215  Description := TStringList.Create;
    129216  Selects := TStringList.Create;
     
    134221destructor TMenuNode.Destroy;
    135222begin
     223  DependsOn.Free;
    136224  Items.Free;
    137   Depends.Free;
    138225  Description.Free;
    139226  Selects.Free;
     
    197284    Add('ID: ' + ID);
    198285    Add('Name: ' + Name);
    199     Add('Depends on: ' + Depends.Text);
     286    Add('Depends on: ' + DependsOn.Show);
    200287    Add('Selects: ' + Selects.Text);
    201288    Add('Description: ' + Description.Text);
     
    245332  LatestNode: TMenuNode;
    246333  CheckList: TObjectList;
     334  DepList: TStringList;
    247335begin
    248336  Result := False;
     
    250338    CheckList := TObjectList.Create;
    251339    CheckList.OwnsObjects := False;
     340    DepList := TStringList.Create;
    252341    if Assigned(Parent) then begin
    253342    Index := Parent.Items.IndexOf(Self);
    254343    if Index = -1 then raise Exception.Create('Node not found in parent');
    255344    if Index >= 1 then TMenuNode(Parent.Items[Index - 1]).AddLastToList(CheckList);
     345    DepList.Clear;
     346    DependsOn.GetList(DepList);
    256347    for I := CheckList.Count - 1 downto 0 do begin
    257       for J := 0 to Depends.Count - 1 do
    258       if Trim(Depends[J]) <> '' then begin
    259         if (Depends[J] = TMenuNode(CheckList[I]).ID) and (TMenuNode(CheckList[I]).ValueType <> vtChoice) then begin
     348      for J := 0 to DepList.Count - 1 do
     349      if Trim(DepList[J]) <> '' then begin
     350        if (DepList[J] = TMenuNode(CheckList[I]).ID) and (TMenuNode(CheckList[I]).ValueType <> vtChoice) then begin
    260351          ChangeParent(TMenuNode(CheckList[I]));
    261352          Result := True;
     
    267358    end;
    268359  finally
     360    DepList.Free;
    269361    CheckList.Free;
    270362  end;
     
    329421end;
    330422
     423function TConfigMenu.IsAlpha(Character: Char): Boolean;
     424begin
     425  Result := ((Character >= 'a') and (Character <= 'z'))
     426    or ((Character >= 'A') and (Character <= 'Z'));
     427end;
     428
     429function TConfigMenu.IsAlphaNumeric(Character: Char): Boolean;
     430begin
     431  Result := IsAlpha(Character) or IsNumeric(Character);
     432end;
     433
     434function TConfigMenu.IsNumeric(Character: Char): Boolean;
     435begin
     436  Result := (Character >= '0') and (Character <= '9');
     437end;
     438
     439function TConfigMenu.IsIdentifier(Name: string): Boolean;
     440var
     441  I: Integer;
     442begin
     443  Result := True;
     444  for I := 1 to Length(Name) do
     445    if not (IsAlphaNumeric(Name[I]) or (Name[I] = '_')) then begin
     446      Result := False;
     447      Break;
     448    end;
     449end;
     450
     451function TConfigMenu.IsSpecialSymbol(Character: Char): Boolean;
     452begin
     453  Result := (Character = '!') or (Character = '=') or (Character = '(') or
     454    (Character = ')') or (Character = '-') or (Character = '|') or (Character = '&');
     455end;
     456
     457procedure TConfigMenu.Expect(var Text: string; Token: string);
     458begin
     459  if GetNextToken(Text) <> Token then
     460    raise Exception.Create('Expected "' + Token + '"');
     461end;
     462
    331463function TConfigMenu.GetNextToken(var Text: string): string;
    332464var
    333465  I: Integer;
    334466  Terminate: Boolean;
    335   State: (stNormal, stWhiteSpace, stString);
     467  State: (stNormal, stWhiteSpace, stString, stSpecialSymbol, stIdent,
     468    stString2);
    336469begin
    337470  I := 1;
     
    350483        State := stNormal;
    351484        Terminate := True;
     485        Inc(I);
     486      end else Result := Result + Text[I];
     487    end else
     488    if State = stString2 then begin
     489      if Text[I] = '''' then begin
     490        State := stNormal;
     491        Terminate := True;
     492        Inc(I);
     493      end else Result := Result + Text[I];
     494    end else
     495    if State = stSpecialSymbol then begin
     496      if not IsSpecialSymbol(Text[I]) or (Result = '(') or (Result = ')') or
     497        ((Result = '!') and (Text[I] <> '=')) or (Result = '||') or
     498        (Result = '&&') then begin
     499        State := stNormal;
     500        Terminate := True;
     501      end else Result := Result + Text[I];
     502    end else
     503    if State = stIdent then begin
     504      if not (IsAlphanumeric(Text[I]) or (Text[I] = '_')) then begin
     505        State := stNormal;
     506        Terminate := True;
    352507      end else Result := Result + Text[I];
    353508    end else begin
    354509      if IsWhiteSpace(Text[I]) then State := stWhiteSpace
    355510      else if Text[I] = '"' then State := stString
     511      else if Text[I] = '''' then State := stString2
     512      else if Text[I] = '#' then begin
     513        // Comment
     514        Text := '';
     515        Terminate := True;
     516      end
     517      else if IsSpecialSymbol(Text[I]) then begin
     518        State := stSpecialSymbol;
     519        Result := Result + Text[I];
     520      end
     521      else if IsAlphaNumeric(Text[I]) then begin
     522        State := stIdent;
     523        Result := Result + Text[I];
     524      end
    356525      else Result := Result + Text[I];
    357526    end;
     
    359528  end;
    360529  Delete(Text, 1, I - 1);
     530end;
     531
     532procedure TConfigMenu.ParseExpression(Node: TMenuNode; Line: string);
     533var
     534  Token: string;
     535  Exp: TExpression;
     536  ExpVar: TExpressionVar;
     537  ExpNew: TExpression;
     538  Neg: Boolean;
     539  Compare: TCompareType;
     540begin
     541  Line := Trim(Line);
     542  Exp := Node.DependsOn;
     543  Neg := False;
     544  while Line <> '' do begin
     545    Token := GetNextToken(Line);
     546    if Token = '||' then begin
     547      Exp.ExpOperator := eoOr;
     548    end else
     549    if Token = '&&' then begin
     550      Exp.ExpOperator := eoAnd;
     551    end else
     552    if Token = '!' then begin
     553      Neg := True;
     554      Continue;
     555    end else
     556    if Token = '(' then begin
     557      ExpNew := TExpression.Create;
     558      ExpNew.Parent := Exp;
     559      Exp.Items.Add(ExpNew);
     560      Exp := ExpNew;
     561      Neg := False;
     562    end else
     563    if Token = ')' then begin
     564      if Assigned(Exp.Parent) then Exp := Exp.Parent
     565        else raise Exception.Create('Cannot go to expression parent.' + GetLog);
     566      Neg := False;
     567    end else
     568    if Token = '' then begin
     569      // White space
     570    end else
     571    if Token = '=' then begin
     572      ExpVar.Compare := ctEqual;
     573      Token := GetNextToken(Line);
     574      ExpVar.Value := Token;
     575      Continue;
     576    end else
     577    if Token = '!=' then begin
     578      ExpVar.Compare := ctNotEqual;
     579      Token := GetNextToken(Line);
     580      ExpVar.Value := Token;
     581      Continue;
     582    end else
     583    if IsIdentifier(Token) then begin
     584      ExpVar := TExpressionVar.Create;
     585      ExpVar.Negative := Neg;
     586      ExpVar.Name := Token;
     587      ExpVar.Compare := Compare;
     588      Exp.Items.Add(ExpVar);
     589      Neg := False;
     590    end else
     591      raise Exception.Create('Unknown token "' + Token + '".' + GetLog);
     592  end;
     593
     594  {// Just try to load symbol list. Do not parse expression
     595  while Trim(Line) <> '' do begin
     596    Parameter := GetNextToken(Line);
     597    if Copy(Parameter, 1, 1) = '!' then Delete(Parameter, 1, 1);
     598    if Copy(Parameter, 1, 1) = '(' then Delete(Parameter, 1, 1);
     599    if Copy(Parameter, Length(Parameter), 1) = ')' then Delete(Parameter, Length(Parameter), 1);
     600    Parameter := Trim(Parameter);
     601    if (Parameter <> '&&') and (Parameter <> '||') then
     602      Node.Depends.Add(Parameter);
     603  end;
     604  }
     605
     606end;
     607
     608function TConfigMenu.GetLog: string;
     609begin
     610  Result := ' ' + ParseFileName + ':' + IntToStr(LineNumber);
    361611end;
    362612
     
    375625  HelpIndent: Integer;
    376626  LineIndent: Integer;
    377 
    378 function GetLog: string;
    379 begin
    380   Result := FileName + ':' + IntToStr(I + 1) + ' ' + Content[I];
    381 end;
    382 
     627  NewExp: TExpressionVar;
    383628const
    384629  TabSize = 8;
    385 
    386 begin
     630begin
     631  ParseFileName := FileName;
    387632  Log('FILE ' + FileName);
    388633  try
     
    394639    HelpIndent := 0;
    395640    for I := 0 to Content.Count - 1 do begin
     641      LineNumber := I + 1;
    396642      Line := MergedLines + Content[I];
    397643      MergedLines := '';
     
    408654        HelpIndent := LineIndent;
    409655        if (State = stHelpStart) and (HelpIndent = 0) then
    410           raise Exception.Create('Error during help parsing');
     656          raise Exception.Create('Error during help parsing.' + GetLog);
    411657      end;
    412658      if (State = stHelpStart) and (Trim(Line) <> '') and (LineIndent < HelpIndent) then
     
    434680      end else
    435681      if (Command = 'bool') or (Command = 'boolean') then begin
    436         Parameter := GetNextToken(Line);
    437         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     682        Expect(Line, '');
     683        Parameter := GetNextToken(Line);
     684        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    438685        NewItem.ValueType := vtBool;
    439686        NewItem.Name := Parameter;
    440687      end else
    441688      if Command = 'def_bool' then begin
    442         Parameter := GetNextToken(Line);
    443         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     689        Expect(Line, '');
     690        Parameter := GetNextToken(Line);
     691        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    444692        NewItem.DefaultValue := Parameter;
    445693        NewItem.ValueType := vtBool;
    446694      end else
    447695      if Command = 'tristate' then begin
    448         Parameter := GetNextToken(Line);
    449         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     696        Expect(Line, '');
     697        Parameter := GetNextToken(Line);
     698        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    450699        NewItem.Name := Parameter;
    451700        NewItem.ValueType := vtTristate;
    452701      end else
    453702      if Command = 'def_tristate' then begin
    454         Parameter := GetNextToken(Line);
    455         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     703        Expect(Line, '');
     704        Parameter := GetNextToken(Line);
     705        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    456706        NewItem.Name := Parameter;
    457707      end else
    458708      if Command = 'string' then begin
    459         Parameter := GetNextToken(Line);
    460         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     709        Expect(Line, '');
     710        Parameter := GetNextToken(Line);
     711        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    461712        NewItem.Name := Parameter;
    462713        NewItem.ValueType := vtString;
    463714      end else
    464715      if Command = 'int' then begin
    465         Parameter := GetNextToken(Line);
    466         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     716        Expect(Line, '');
     717        Parameter := GetNextToken(Line);
     718        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    467719        NewItem.Name := Parameter;
    468720        NewItem.ValueType := vtInt;
    469721      end else
    470722      if Command = 'hex' then begin
    471         Parameter := GetNextToken(Line);
    472         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     723        Expect(Line, '');
     724        Parameter := GetNextToken(Line);
     725        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    473726        NewItem.Name := Parameter;
    474727        NewItem.ValueType := vtHex;
    475728      end else
    476729      if Command = 'range' then begin
    477         Parameter := GetNextToken(Line);
    478         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     730        Expect(Line, '');
     731        Parameter := GetNextToken(Line);
     732        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    479733        NewItem.RangeMin := Parameter;
    480734        Parameter := GetNextToken(Line);
     
    482736      end else
    483737      if Command = 'prompt' then begin
    484         Parameter := GetNextToken(Line);
    485         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     738        Expect(Line, '');
     739        Parameter := GetNextToken(Line);
     740        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    486741        NewItem.Name := Parameter;
    487742      end else
    488743      if Command = 'default' then begin
    489         Parameter := GetNextToken(Line);
    490         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     744        Expect(Line, '');
     745        Parameter := GetNextToken(Line);
     746        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    491747        NewItem.DefaultValue := Parameter;
    492748      end else
    493749      if Command = 'depends' then begin
     750        Expect(Line, '');
    494751        Parameter := GetNextToken(Line);
    495752        if Parameter = 'on' then begin
    496           if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
    497           // Just try to load symbol list. Do not parse expression
    498           while Trim(Line) <> '' do begin
    499             Parameter := GetNextToken(Line);
    500             if Copy(Parameter, 1, 1) = '!' then Delete(Parameter, 1, 1);
    501             if Copy(Parameter, 1, 1) = '(' then Delete(Parameter, 1, 1);
    502             if Copy(Parameter, Length(Parameter), 1) = ')' then Delete(Parameter, Length(Parameter), 1);
    503             Parameter := Trim(Parameter);
    504             if (Parameter <> '&&') and (Parameter <> '||') then
    505               NewItem.Depends.Add(Parameter);
    506           end;
     753          if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
     754          ParseExpression(NewItem, Line);
    507755        end;
    508756      end else
    509757      if Command = 'select' then begin
    510         Parameter := GetNextToken(Line);
    511         if not Assigned(NewItem) then raise Exception.Create('Item not defined. ' + GetLog);
     758        Expect(Line, '');
     759        Parameter := GetNextToken(Line);
     760        if not Assigned(NewItem) then raise Exception.Create('Item not defined.' + GetLog);
    512761        NewItem.Selects.Add(Parameter);
    513762      end else
     
    524773      end else
    525774      if Command = 'option' then begin
     775        Expect(Line, '');
    526776        Parameter := GetNextToken(Line);
    527777      end else
    528778      if (Command = 'config') or (Command = 'menuconfig') then begin
     779        Expect(Line, '');
    529780        Parameter := GetNextToken(Line);
    530781        State := stConfig;
     
    532783        NewItem.Parent := CurrentMenu;
    533784        NewItem.ID := Parameter;
    534         NewItem.Depends.AddStrings(ConditionStack);
     785        for J := 0 to ConditionStack.Count - 1 do
     786        if ConditionStack[J] <> '' then
     787        begin
     788          NewExp := TExpressionVar.Create;
     789          NewExp.Name := ConditionStack[J];
     790          NewItem.DependsOn.Items.Add(NewExp);
     791        end;
    535792        CurrentMenu.Items.Add(NewItem);
    536793        if Command = 'menuconfig' then NewItem.MenuConfig := True;
    537794      end else
    538795      if (Command = 'comment')  then begin
     796        Expect(Line, '');
    539797        Parameter := GetNextToken(Line);
    540798        NewItem := TMenuNode.Create;
    541799        NewItem.Parent := CurrentMenu;
    542800        NewItem.Name := Parameter;
    543         NewItem.Depends.AddStrings(ConditionStack);
     801        for J := 0 to ConditionStack.Count - 1 do
     802        if ConditionStack[J] <> '' then begin
     803          NewExp := TExpressionVar.Create;
     804          NewExp.Name := ConditionStack[J];
     805          NewItem.DependsOn.Items.Add(NewExp);
     806        end;
    544807        NewItem.ValueType := vtComment;
    545808        CurrentMenu.Items.Add(NewItem);
    546809      end else
    547810      if Command = 'source' then begin
     811        Expect(Line, '');
    548812        Parameter := GetNextToken(Line);
    549813        if Pos('$SRCARCH', Parameter) > 0 then
     
    552816        if FileExistsUTF8(Parameter) then
    553817          ParseFile(Parameter)
    554           else raise Exception.Create('Source file "' + Parameter + '" not found. ' + GetLog);
     818          else raise Exception.Create('Source file "' + Parameter + '" not found.' + GetLog);
    555819      end else
    556820      if Command = 'choice' then begin
     821        Expect(Line, '');
    557822        Parameter := GetNextToken(Line);
    558823        NewMenu := TMenuNode.Create;
     
    560825        NewMenu.Name := Parameter;
    561826        NewMenu.Parent := CurrentMenu;
    562         NewMenu.Depends.AddStrings(ConditionStack);
     827        for J := 0 to ConditionStack.Count - 1 do
     828        if ConditionStack[J] <> '' then begin
     829          NewExp := TExpressionVar.Create;
     830          NewExp.Name := ConditionStack[J];
     831          NewMenu.DependsOn.Items.Add(NewExp);
     832        end;
    563833        ConditionStack.AddObject('', nil);
    564834        NewItem := NewMenu;
     
    570840          ConditionStack.Delete(ConditionStack.Count - 1);
    571841          CurrentMenu := CurrentMenu.Parent;
    572         end else raise Exception.Create('Can''t change menu level up. ' + GetLog);
     842        end else raise Exception.Create('Can''t change menu level up.' + GetLog);
    573843      end else
    574844      if Command = 'mainmenu' then begin
     845        Expect(Line, '');
    575846        Parameter := GetNextToken(Line);
    576847        Parameter := StringReplace(Parameter, '$ARCH', Arch, [rfReplaceAll]);
     
    579850      end else
    580851      if Command = 'menu' then begin
     852        Expect(Line, '');
    581853        Parameter := GetNextToken(Line);
    582854        Log('MENU ' + Parameter + ' IN ' + CurrentMenu.GetAbsoluteName);
     
    584856        NewMenu.Name := Parameter;
    585857        NewMenu.Parent := CurrentMenu;
    586         NewMenu.Depends.AddStrings(ConditionStack);
     858        for J := 0 to ConditionStack.Count - 1 do
     859        if ConditionStack[J] <> '' then begin
     860          NewExp := TExpressionVar.Create;
     861          NewExp.Name := ConditionStack[J];
     862          NewMenu.DependsOn.Items.Add(NewExp);
     863        end;
    587864        ConditionStack.AddObject('', nil);
    588865        NewItem := NewMenu;
     
    595872          ConditionStack.Delete(ConditionStack.Count - 1);
    596873          CurrentMenu := CurrentMenu.Parent;
    597         end else raise Exception.Create('Can''t change menu level up. ' + GetLog);
     874        end else raise Exception.Create('Can''t change menu level up.' + GetLog);
    598875      end else
    599876      if Command = 'if' then begin
     877        Expect(Line, '');
    600878        ConditionStack.AddObject(GetNextToken(Line), NewItem);
    601879      end else
     
    606884        ConditionStack.Delete(ConditionStack.Count - 1);
    607885      end else
    608         raise Exception.Create('Unknown command "' + Command + '". ' + GetLog);
     886        raise Exception.Create('Unknown command "' + Command + '".' + GetLog);
    609887    end;
    610888  finally
Note: See TracChangeset for help on using the changeset viewer.