mirror of
https://github.com/chenasraf/search-ast-parser-js.git
synced 2026-05-18 01:49:07 +00:00
fix(parser): properly parse side tokens
This commit is contained in:
@@ -17,8 +17,17 @@ test('should parse OR operator', () => {
|
|||||||
const lexer = new Lexer(reader)
|
const lexer = new Lexer(reader)
|
||||||
const parser = new Parser(lexer)
|
const parser = new Parser(lexer)
|
||||||
const tokens = parser.parse()
|
const tokens = parser.parse()
|
||||||
const wordToken = tokens[0] as Operator
|
expect(tokens[0]).toEqual({
|
||||||
expect(wordToken.type).toBe('operator')
|
type: 'operator',
|
||||||
expect(wordToken.left.value).toBe('word')
|
value: 'or',
|
||||||
expect(wordToken.right.value).toBe('phrase')
|
left: {
|
||||||
|
type: 'word',
|
||||||
|
value: 'word',
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
type: 'phrase',
|
||||||
|
value: 'phrase',
|
||||||
|
quote: '"',
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -134,33 +134,48 @@ export class Parser extends IParser {
|
|||||||
nextToken = this.lexer.peek(1)
|
nextToken = this.lexer.peek(1)
|
||||||
this.lexer.consume()
|
this.lexer.consume()
|
||||||
}
|
}
|
||||||
if (nextToken?.token === 'operator') {
|
// lookahead
|
||||||
this.index++
|
switch (nextToken?.token) {
|
||||||
return this.consumeOperator(token!, nextToken)
|
|
||||||
}
|
|
||||||
switch (token?.token) {
|
|
||||||
case LexerToken.word:
|
|
||||||
return { type: 'word', value: this.lexer.consume()!.value }
|
|
||||||
case LexerToken.quote:
|
|
||||||
return this.consumePhrase(token)
|
|
||||||
case LexerToken.operator:
|
case LexerToken.operator:
|
||||||
return this.consumeOperator(token, nextToken!)
|
this.index++
|
||||||
default:
|
return this.consumeOperator(this.parseNormalLexToken(token!)!, nextToken)
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no special token coming up, proceed with this token
|
||||||
|
this.lexer.consume()
|
||||||
|
return this.parseNormalLexToken(token)
|
||||||
default:
|
default:
|
||||||
throw new Error('Bad state')
|
throw new Error('Bad state')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private consumePhrase(token: LexerTokenValue): ParserToken | null {
|
private parseNormalLexToken(token: LexerTokenValue | null): ParserToken | null {
|
||||||
this.lexer.consume()
|
switch (token?.token) {
|
||||||
const quoteContent = this.lexer.consume()!
|
case LexerToken.word:
|
||||||
this.lexer.consume()
|
return this.consumeWord(token)
|
||||||
|
case LexerToken.quote:
|
||||||
|
// TODO might need to reconsider consuming here.
|
||||||
|
const quoteContent = this.lexer.consume()!
|
||||||
|
this.lexer.consume()
|
||||||
|
return this.consumePhrase(token, quoteContent)
|
||||||
|
// case LexerToken.operator:
|
||||||
|
// return this.consumeOperator(token, nextToken!)
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private consumeWord(word: LexerTokenValue): ParserToken | null {
|
||||||
|
// TODO might need to reconsider consuming here.
|
||||||
|
return { type: 'word', value: word.value }
|
||||||
|
}
|
||||||
|
|
||||||
|
private consumePhrase(token: LexerTokenValue, quoteContent: LexerTokenValue): ParserToken | null {
|
||||||
|
// TODO might need to reconsider consuming here.
|
||||||
return { type: 'phrase', value: quoteContent.value, quote: token.value as '"' }
|
return { type: 'phrase', value: quoteContent.value, quote: token.value as '"' }
|
||||||
}
|
}
|
||||||
|
|
||||||
private consumeOperator(left: LexerTokenValue, opToken: LexerTokenValue): ParserToken | null {
|
private consumeOperator(left: ParserToken, opToken: LexerTokenValue): ParserToken | null {
|
||||||
this.index++
|
this.index++
|
||||||
this.lexer.consume()
|
this.lexer.consume()
|
||||||
const right = this.readNextToken()
|
const right = this.readNextToken()
|
||||||
|
|||||||
Reference in New Issue
Block a user