private void parseKeywordAndArgs() {

    if (!keyword_parsed) {
      keyword_parsed = true;
      ParsedString keywordOrSetting = line.arguments.get(argOff);
      keywordSequence_isSetting = keywordOrSetting.getValue().startsWith("[");
      if (keywordSequence_isSetting) {
        keywordSequence_keywordCallState = KeywordCallState.UNDETERMINED_NOT_FOR_NOINDENT; // TODO
        // possibly
        // should
        // be
        // KEYWORD_NOT_FOR_NOINDENT
        keywordSequence_settingType = keywordSequenceSettingTypes.get(keywordOrSetting.getValue());
        if (keywordSequence_settingType == null) {
          keywordSequence_settingType = SettingType.UNKNOWN;
        }
        keywordOrSetting.setType(ArgumentType.SETTING_KEY);
        prepareNextToken();
      } else {
        keywordSequence_keywordCallState = KeywordCallState.UNDETERMINED;
        parseKeywordCall(lastRealType.isTestCaseLine());
      }
    } else {
      if (keywordSequence_isSetting) {
        parseKeywordSequenceSetting();
      } else {
        parseKeywordCall(lastRealType.isTestCaseLine());
      }
    }
  }
 private void parseTableBeginToken() {
   assert argOff == 0;
   ParsedString table = line.arguments.get(0);
   table.setType(ArgumentType.TABLE);
   prepareNextLine();
   return;
 }
 void prepareNextLine() {
   assert argOff >= 0;
   assert argOff <= argLen;
   // if previous line ended with comment, add it to queue now
   if (lineEndsWithComment) {
     ParsedString comment = line.arguments.get(argLen);
     if (comment.getValue().startsWith("#")) {
       comment.setType(ArgumentType.COMMENT);
     }
   }
   // next line
   line = getNextNonemptyLine();
   if (line != null) {
     argLen = line.arguments.size();
     lineEndsWithComment = line.arguments.get(argLen - 1).getValue().startsWith("#");
     if (lineEndsWithComment) {
       --argLen; // exclude now, deal with it later (see top of method)
     }
   } else {
     // for (RobotLine line : lines) {
     // System.out.println(line);
     // }
     lines = null;
     lineIterator = null;
     argLen = 0;
     lineEndsWithComment = false;
   }
   argOff = 0;
 }
 private void parseVariableTableLineToken() {
   switch (argOff) {
     case 0:
       ParsedString variable = line.arguments.get(0);
       variable.setType(ArgumentType.VARIABLE_KEY);
       prepareNextToken();
       return;
     default:
       parseVariableArgs();
       return;
   }
 }
 private void parseTestCaseOrKeywordTableBegin(LineType type) {
   if (argOff == 0) {
     keyword_parsed = false;
     lookForLocalTestTemplate();
     ParsedString newName = line.arguments.get(0);
     if (!newName.isEmpty()) {
       boolean isTestCase = type == LineType.TESTCASE_TABLE_TESTCASE_BEGIN;
       newName.setType(isTestCase ? ArgumentType.NEW_TESTCASE : ArgumentType.NEW_KEYWORD);
     }
     prepareNextToken();
     return;
   }
   parseTestCaseOrKeywordLineToken();
   return;
 }
 private void parseSettingTableLineToken() {
   switch (argOff) {
     case 0:
       {
         ParsedString setting = line.arguments.get(0);
         setting.setType(ArgumentType.SETTING_KEY);
         setting_type = settingTypes.get(setting.getValue());
         if (setting_type == null) {
           setting_type = SettingType.UNKNOWN;
         }
         setting_gotFirstArg = false;
         // TODO possibly should be KEYWORD_NOT_FOR_NOINDENT:
         keywordSequence_keywordCallState = KeywordCallState.UNDETERMINED_NOT_FOR_NOINDENT;
         prepareNextToken();
         return;
       }
     default:
       {
         parseSettingArgs();
         return;
       }
   }
 }
 /**
  * Before this is called the first time, keywordSequence_keywordCallState must be initialized to
  * either UNDETERMINED, UNDETERMINED_NOINDENT, KEYWORD_NOINDENT, KEYWORD_NOT_FOR_NOINDENT
  *
  * @param templatesEnabled whether the template flags {@link #globalTemplateAtLine} and {@link
  *     #localTemplateAtLine} affect keyword calls during this invocation
  */
 private void parseKeywordCall(boolean templatesEnabled) {
   if (keywordSequence_keywordCallState.isUndetermined()) {
     keywordSequence_keywordCallState =
         determineInitialKeywordCallState(keywordSequence_keywordCallState);
   }
   switch (keywordSequence_keywordCallState) {
     case LVALUE_NOINDENT:
     case LVALUE:
       {
         ParsedString variable = line.arguments.get(argOff);
         if (!variable.isEmpty()
             || keywordSequence_keywordCallState == KeywordCallState.LVALUE_NOINDENT) {
           variable.setType(ArgumentType.KEYWORD_LVALUE);
           if (variable.getValue().endsWith("=")) {
             keywordSequence_keywordCallState = KeywordCallState.KEYWORD_NOT_FOR_NOINDENT;
           }
         }
         prepareNextToken();
         return;
       }
     case KEYWORD_NOT_FOR_NOINDENT:
     case KEYWORD:
       {
         ParsedString keyword = line.arguments.get(argOff);
         if (!keyword.isEmpty()
             || keywordSequence_keywordCallState == KeywordCallState.KEYWORD_NOT_FOR_NOINDENT) {
           if (keyword.getValue().equals(":FOR")
               && keywordSequence_keywordCallState != KeywordCallState.KEYWORD_NOT_FOR_NOINDENT) {
             keyword.setType(ArgumentType.FOR_PART);
             keywordSequence_keywordCallState = KeywordCallState.FOR_VARS;
           } else {
             if (templatesEnabled && isTemplateActive()) {
               keyword.setType(ArgumentType.KEYWORD_ARG);
               // TODO support "Run Keyword If" etc as template keyword
               keywordSequence_keywordArgPos = KEYWORD_ARG_POS_NONE;
             } else if (NONE_STR.equals(keyword.getValue())) {
               // TODO verify what is this branch about
               keyword.setType(ArgumentType.SETTING_VAL);
               keywordSequence_keywordArgPos = KEYWORD_ARG_POS_NONE;
             } else {
               keyword.setType(ArgumentType.KEYWORD_CALL);
               setUpKeywordArgPos(keyword);
             }
             keywordSequence_keywordCallState = KeywordCallState.KEYWORD_ARGS;
           }
         }
         prepareNextToken();
         return;
       }
     case FOR_VARS:
       {
         ParsedString arg = line.arguments.get(argOff);
         String argVal = arg.getValue();
         if (argVal.equals("IN") || argVal.equals("IN RANGE")) {
           arg.setType(ArgumentType.FOR_PART);
           keywordSequence_keywordCallState = KeywordCallState.FOR_ARGS;
           prepareNextToken();
           return;
         }
         arg.setType(ArgumentType.KEYWORD_LVALUE);
         prepareNextToken();
         return;
       }
     case FOR_ARGS:
       {
         setArgTypesToEol(ArgumentType.KEYWORD_ARG);
         prepareNextLine();
         return;
       }
     case KEYWORD_ARGS:
       {
         ParsedString arg = line.arguments.get(argOff);
         boolean isKeyword;
         switch (keywordSequence_keywordArgPos) {
           case KEYWORD_ARG_POS_NONE:
             isKeyword = false;
             break;
           case KEYWORD_ARG_POS_ALL:
             isKeyword = true;
             break;
           default:
             isKeyword = keywordSequence_currentArgPos++ == keywordSequence_keywordArgPos;
             if (isKeyword) {
               setUpKeywordArgPos(arg);
             }
             break;
         }
         if (isKeyword) {
           arg.setType(ArgumentType.KEYWORD_CALL_DYNAMIC);
         } else {
           arg.setType(ArgumentType.KEYWORD_ARG);
         }
         prepareNextToken();
         return;
       }
     default:
       throw new RuntimeException();
   }
 }
 private void parseSettingArgs() {
   switch (setting_type) {
     case UNKNOWN:
       {
         prepareNextLine();
         return;
       }
     case STRING:
       {
         setArgTypesToEol(ArgumentType.SETTING_VAL);
         prepareNextLine();
         return;
       }
     case FILE:
       {
         ParsedString file = line.arguments.get(argOff);
         file.setType(ArgumentType.SETTING_FILE);
         prepareNextLine();
         return;
       }
     case FILE_ARGS:
       {
         if (!setting_gotFirstArg) {
           ParsedString file = line.arguments.get(argOff);
           file.setType(ArgumentType.SETTING_FILE);
           prepareNextToken();
           setting_gotFirstArg = true;
           setting_withNameState = WithNameState.NONE;
           return;
         } else {
           switch (setting_withNameState) {
             case NONE:
               ParsedString arg = line.arguments.get(argOff);
               if (arg.getValue().equals("WITH NAME")) {
                 setting_withNameState = WithNameState.GOT_KEY;
                 arg.setType(ArgumentType.SETTING_FILE_WITH_NAME_KEY);
               } else {
                 arg.setType(ArgumentType.SETTING_FILE_ARG);
               }
               prepareNextToken();
               return;
             case GOT_KEY:
               ParsedString name = line.arguments.get(argOff);
               name.setType(ArgumentType.SETTING_FILE_WITH_NAME_VALUE);
               setting_withNameState = WithNameState.GOT_VALUE;
               prepareNextLine();
               return;
             case GOT_VALUE:
               prepareNextLine();
               return;
           }
         }
         throw new RuntimeException();
       }
     case KEYWORD_ARGS:
       {
         parseKeywordCall(false);
         return;
       }
   }
   throw new RuntimeException();
 }