private JobDescriptor parseJobDescriptor() {
		JobDescriptor jd = null;
		// Double identifiers indicates job definition
		if (tokens.peek(0, TokenKind.IDENTIFIER)) {
			if (tokens.peek(1, TokenKind.IDENTIFIER)) {
				if (SUPPORTS_INLINE_JOB_DEFINITIONS) {
					jd = parseJobDefinition();
				}
				else {
					tokens.raiseException(tokens.peek(1).startpos, JobDSLMessage.EXPECTED_FLOW_OR_SPLIT_CHARS,
							tokens.peek(1).stringValue());
				}
			}
			else {
				jd = parseJobReference(false);
			}
		}
		if (jd == null) {
			Token t = tokens.peek();
			tokens.raiseException(t == null ? 0 : t.startpos, JobDSLMessage.EXPECTED_JOB_REF_OR_DEF);
		}
		if (tokens.peek(TokenKind.PIPE)) {
			List<Transition> transitions = parseTransitions();
			jd.setTransitions(transitions);
		}
		return jd;
	}
Parse a job flow definition into an abstract syntax tree (AST).

@param jobSpecification the textual job specification
@return the AST for the parsed job
@throws JobSpecificationException if any problems occur during parsing
spring-xd-dirt/src/main/java/org/springframework/xd/dirt/job/dsl/JobParser.java