Skip to content

Commit

Permalink
feature: make peek more useful by passing group and value
Browse files Browse the repository at this point in the history
  • Loading branch information
stagas committed Nov 28, 2021
1 parent 82fbae2 commit 2ed6d2a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 6 deletions.
64 changes: 60 additions & 4 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('createLexer', () => {
expect(error?.message).toContain('Unexpected')
}

expect(l.accept('foo')).toBeUndefined()
expect(l.accept('foo')).toBeNull()

expect(l.peek()).toEqual({
group: 'ident',
Expand Down Expand Up @@ -70,15 +70,15 @@ describe('createLexer', () => {
const lexer = createLexer(tokenizer)
const l = lexer('foo bar baz')

expect(l.accept('ident', 'hello')).toBeUndefined()
expect(l.accept('any', 'foo')).toBeUndefined()
expect(l.accept('ident', 'hello')).toBeNull()
expect(l.accept('any', 'foo')).toBeNull()
expect(l.accept('ident', 'foo')).toEqual({
group: 'ident',
value: 'foo',
index: 0
})

expect(l.accept('ident', 'foo')).toBeUndefined()
expect(l.accept('ident', 'foo')).toBeNull()
expect(l.accept('ident', 'bar')).toEqual({
group: 'ident',
value: 'bar',
Expand Down Expand Up @@ -201,4 +201,60 @@ describe('createLexer', () => {
expect(source).toEqual({ input })
expect(l.advance()!.source).toBe(source)
})

it('peek(group?, value?)', () => {
const tokenizer = (input: string) =>
input.matchAll(/(?<ident>[a-z]+)|(?<number>[0-9]+)/g)
const lexer = createLexer(tokenizer)

const l = lexer('foo 0123 bar 456 baz')

expect(l.peek()).toEqual({
group: 'ident',
value: 'foo',
index: 0
})

expect(l.peek('ident')).toEqual({
group: 'ident',
value: 'foo',
index: 0
})

expect(l.peek('ident', 'foo')).toEqual({
group: 'ident',
value: 'foo',
index: 0
})

expect(l.peek('ident', 'yo')).toBeNull()

expect(l.peek('number')).toBeNull()

expect(l.peek('number', '0123')).toBeNull()

l.advance()

expect(l.peek()).toEqual({
group: 'number',
value: '0123',
index: 4
})

expect(l.peek('number')).toEqual({
group: 'number',
value: '0123',
index: 4
})

expect(l.peek('number', '0123')).toEqual({
group: 'number',
value: '0123',
index: 4
})

expect(l.peek('number', '012')).toBeNull()

expect(l.peek('ident')).toBeNull()
})
})
18 changes: 16 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,13 @@ export interface Lexer {
advance: () => LexerToken
/**
* Returns token under current position.
* When passed a `group` and maybe a `value` it will only return
* the token if they match, otherwise will return `null`.
*
* @param group The group name to examine
* @param value The value to match
*/
peek: () => LexerToken
peek: (group?: string, value?: string) => LexerToken | null
/**
* Advances position only when current `token.group` matches `group`,
* and optionally when `token.value` matches `value`,
Expand Down Expand Up @@ -165,7 +170,16 @@ export const createLexer =

const advance = () => (([last, curr] = [curr, next()]), last)

const peek = () => curr
const peek = (group?: string, value?: string) =>
group != null
? curr.group === group
? value != null
? curr.value === value
? curr
: null
: curr
: null
: curr

const accept = (group: string, value?: string) =>
curr.group === group && (value == null ? true : curr.value === value)
Expand Down

0 comments on commit 2ed6d2a

Please sign in to comment.