github.com/googlecloudplatform/kubernetes-workshops@v0.0.0-20180501174420-d8199445b2c3/test/parser.go (about)

     1  // Copyright 2016 Google, Inc
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package main
    15  
    16  import (
    17  	"bufio"
    18  	"errors"
    19  	"io"
    20  	"strings"
    21  )
    22  
    23  // An Action is one instance of a START/END tag pair. ActionType is
    24  // the word following START. Lines are the lines between the tags.
    25  type Action struct {
    26  	ActionType string
    27  	Lines      []string
    28  	closed     bool
    29  }
    30  
    31  type stateFn func(string, *[]Action) (stateFn, error)
    32  
    33  func neutralState(line string, actions *[]Action) (stateFn, error) {
    34  	words := strings.Fields(line)
    35  	for index, word := range words {
    36  		if word == "END" {
    37  			return nil, errors.New("Unexpected END tag outside action")
    38  		}
    39  		if word == "START" {
    40  			action := words[index+1]
    41  			newAction(action, actions)
    42  			return insideActionState, nil
    43  		}
    44  	}
    45  	return neutralState, nil
    46  }
    47  
    48  func insideActionState(line string, actions *[]Action) (stateFn, error) {
    49  	words := strings.Fields(line)
    50  	if strings.HasPrefix(line, "```") || words[0] == "```" {
    51  		// Ignore line.
    52  		return insideActionState, nil
    53  	}
    54  	for _, word := range words {
    55  		if word == "END" {
    56  			closeAction(*actions)
    57  			return neutralState, nil
    58  		}
    59  		if word == "START" {
    60  			return nil, errors.New("Unexpected START tag inside action")
    61  		}
    62  	}
    63  	actionLine(line, *actions)
    64  	return insideActionState, nil
    65  }
    66  
    67  func newAction(aType string, actions *[]Action) {
    68  	aa := Action{
    69  		ActionType: aType,
    70  		Lines:      make([]string, 0),
    71  		closed:     false,
    72  	}
    73  	*actions = append(*actions, aa)
    74  }
    75  
    76  func actionLine(line string, actions []Action) {
    77  	actions[len(actions)-1].Lines =
    78  		append(actions[len(actions)-1].Lines, line)
    79  }
    80  
    81  func closeAction(actions []Action) {
    82  	actions[len(actions)-1].closed = true
    83  }
    84  
    85  // GetActions parses the input for START/END tags and compiles a list
    86  // of actions, comprising of the lines between the lines with
    87  // START/END. Lines that begin with ``` are ignored. The word
    88  // immediately after START is saved as the action type.
    89  func GetActions(reader io.Reader) ([]Action, error) {
    90  	scanner := bufio.NewScanner(reader)
    91  	actions := make([]Action, 0)
    92  
    93  	for state := neutralState; scanner.Scan(); {
    94  		var err error
    95  		state, err = state(scanner.Text(), &actions)
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  	}
   100  	if err := scanner.Err(); err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	return actions, nil
   105  }