m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/src/lexer.js
blob: 6b75129e52f2f0bb664fb8409b85d8174eff260d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
const lexemeTypes = []

const newLexemeType = (type, regex, adder) => {
  lexemeTypes.push({
    type,
    regex: new RegExp(`^(${regex})(.*)$`),
    adder: adder || (lexemes => { lexemes.push({ type }) })
  })
}

const newValueLexeme = (type, regex, converter = v => v) => {
  newLexemeType(type, regex, (lexemes, value) => {
    lexemes.push({ type, value: converter(value) })
  })
}

newValueLexeme('constant', '\\d+', Number)
newLexemeType('d', 'd')
newLexemeType('bigPlus', ' \\+ ' )
newLexemeType('bigMinus', ' - ')
newLexemeType('bigTimes', ' \\* ')
newLexemeType('bigDivide', ' / ')
newLexemeType('plus', '\\+')
newLexemeType('minus', '-')
newLexemeType('times', '\\*')
newLexemeType('divide', '/')
newLexemeType('(', '\\(')
newLexemeType(')', '\\)')
newLexemeType('E', 'E')
newLexemeType('e', 'e')
newLexemeType('K', 'K')
newLexemeType('k', 'k')
newLexemeType('A', 'A')
newLexemeType('a', 'a')
newLexemeType('T', 'T')
newLexemeType('t', 't')
newLexemeType(' x ', ' x ')

const lex = (expressionString) => {
  let lexemes = []

  while (expressionString.length > 0) {
    let matched = false

    lexemeTypes.forEach(lexemeType => {
      let matches = lexemeType.regex.exec(expressionString)

      if (matches) {
        matched = true
        lexemeType.adder(lexemes, matches[1])
        expressionString = matches[2]
      }
    })

    if (!matched) {
      throw new Error('Syntax error: unrecognized token')
    }
  }

  return lexemes
}

exports.lex = lex