You can achieve this in a few steps with NLTK:
PoS tag the sequences
generate the desired n-grams (in your examples there are no trigrams, but skip-grams which can be generated through trigrams and then punching out the middle token)
discard all n-grams that don't match the pattern JJ NN.
Example:
def jjnn_pairs(phrase):
'''
Iterate over pairs of JJ-NN.
'''
tagged = nltk.pos_tag(nltk.word_tokenize(phrase))
for ngram in ngramise(tagged):
tokens, tags = zip(*ngram)
if tags == ('JJ', 'NN'):
yield tokens
def ngramise(sequence):
'''
Iterate over bigrams and 1,2-skip-grams.
'''
for bigram in nltk.ngrams(sequence, 2):
yield bigram
for trigram in nltk.ngrams(sequence, 3):
yield trigram[0], trigram[2]
Extend the pattern ('JJ', 'NN')
and the desired n-grams to your needs.
I think there is no need for parsing.
The major problem of this approach, however, is that most PoS taggers will probably not tag everything exactly the way you want.
For example, the default PoS tagger of my NLTK installation tagged "chili" as NN, not JJ, and "fried" got VBD.
Parsing won't help you with that, though!