fix(parser): properly parse side tokens

This commit is contained in:
Chen Asraf
2022-08-16 01:35:11 +03:00
parent 6f3329c601
commit 7e27bc32aa
2 changed files with 45 additions and 21 deletions

View File

@@ -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: '"',
},
})
}) })

View File

@@ -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()