Parse is the main function to parse a Makefile from a file path string to a Makefile struct. This function should be kept fairly small and ideally most of the heavy lifting will live in the specific parsing functions below that know how to deal with individual lines.
(filepath string)
| 87 | // of the heavy lifting will live in the specific parsing functions below that |
| 88 | // know how to deal with individual lines. |
| 89 | func Parse(filepath string) (ret Makefile, err error) { |
| 90 | ret.FileName = filepath |
| 91 | var scanner *MakefileScanner |
| 92 | scanner, err = NewMakefileScanner(filepath) |
| 93 | if err != nil { |
| 94 | return ret, err |
| 95 | } |
| 96 | |
| 97 | for { |
| 98 | switch { |
| 99 | case strings.HasPrefix(scanner.Text(), "#"): |
| 100 | // parse comments here, ignoring them for now |
| 101 | scanner.Scan() |
| 102 | case strings.HasPrefix(scanner.Text(), "."): |
| 103 | if matches := reFindSpecialTarget.FindStringSubmatch(scanner.Text()); matches != nil { |
| 104 | // Treat special targets like .PHONY or .DEFAULT_GOAL as rules, not variables |
| 105 | specialRule := Rule{ |
| 106 | Target: strings.TrimSpace(matches[1]), |
| 107 | Dependencies: strings.Fields(strings.TrimSpace(matches[2])), |
| 108 | Body: nil, |
| 109 | FileName: filepath, |
| 110 | LineNumber: scanner.LineNumber, |
| 111 | } |
| 112 | ret.Rules = append(ret.Rules, specialRule) |
| 113 | } |
| 114 | scanner.Scan() |
| 115 | default: |
| 116 | // parse target or variable here, the function advances the scanner |
| 117 | // itself to be able to detect rule bodies |
| 118 | ruleOrVariable, parseError := parseRuleOrVariable(scanner) |
| 119 | if parseError != nil { |
| 120 | return ret, parseError |
| 121 | } |
| 122 | switch v := ruleOrVariable.(type) { |
| 123 | case Rule: |
| 124 | ret.Rules = append(ret.Rules, v) |
| 125 | case Variable: |
| 126 | ret.Variables = append(ret.Variables, v) |
| 127 | } |
| 128 | |
| 129 | } |
| 130 | |
| 131 | if scanner.Finished { |
| 132 | return |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | // parseRuleOrVariable gets the parsing scanner in a state where it resides on |
| 138 | // a line that could be a variable or a rule. The function parses the line and |