@renatorib/

parser-v2

Nodejs

No description

fork
loading
Files
  • index.js

This Plugin Crashed!

Error: Error: must not create an existing file {"type":"CREATE_FILE","wid":"0.9409977689728515","path":"index.js","file":{"path":"index.js","content":{"asEncoding":{"base64":"Y29uc3QgbGV4ZXIgPSBpbnB1dCA9PiB7CiAgbGV0IHRva2VucyA9IFtdCiAgbGV0IGN1cnJlbnQgPSAwCiAgCiAgd2hpbGUgKGN1cnJlbnQgPCBpbnB1dC5sZW5ndGgpIHsKICAgIGxldCBjaGFyID0gaW5wdXRbY3VycmVudF0KICAgIAogICAgaWYgKGNoYXIgPT09ICIgIikgewogICAgICBjdXJyZW50KysKICAgICAgY29udGludWUKICAgIH0KCiAgICBpZiAoY2hhciA9PT0gIisiKSB7CiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogIlBsdXMiIH0pCiAgICAgIGN1cnJlbnQrKwogICAgICBjb250aW51ZQogICAgfQoKICAgIGlmIChjaGFyID09PSAiLSIpIHsKICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiAiTWludXMiIH0pCiAgICAgIGN1cnJlbnQrKwogICAgICBjb250aW51ZQogICAgfQoKICAgIGlmIChjaGFyID09PSAiKiIpIHsKICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiAiU3RhciIgfSkKICAgICAgY3VycmVudCsrCiAgICAgIGNvbnRpbnVlCiAgICB9CgogICAgaWYgKGNoYXIgPT09ICIvIikgewogICAgICB0b2tlbnMucHVzaCh7IHR5cGU6ICJTbGFzaCIgfSkKICAgICAgY3VycmVudCsrCiAgICAgIGNvbnRpbnVlCiAgICB9CiAgICAKICAgIGlmIChjaGFyID09PSAiKCIpIHsKICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiAiTGVmdFBhcmVuIiB9KQogICAgICBjdXJyZW50KysKICAgICAgY29udGludWUKICAgIH0KCiAgICBpZiAoY2hhciA9PT0gIikiKSB7CiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogIlJpZ2h0UGFyZW4iIH0pCiAgICAgIGN1cnJlbnQrKwogICAgICBjb250aW51ZQogICAgfQoKICAgIGlmICgvWzAtOV0vLnRlc3QoY2hhcikpIHsKICAgICAgbGV0IHZhbHVlID0gJycKCiAgICAgIHdoaWxlICgvWzAtOV0vLnRlc3QoY2hhcikpIHsKICAgICAgICB2YWx1ZSArPSBjaGFyCiAgICAgICAgY3VycmVudCsrCiAgICAgICAgY2hhciA9IGlucHV0W2N1cnJlbnRdCiAgICAgIH0KICAgICAgCiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogIk51bWJlciIsIHZhbHVlOiBwYXJzZUludCh2YWx1ZSwgMTApIH0pCiAgICAgIAogICAgICBjb250aW51ZQogICAgfQoKICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBjaGFyICR7Y2hhcn1gKQogIH0KCiAgdG9rZW5zLnB1c2goeyB0eXBlOiAiRW5kIiB9KQogIAogIHJldHVybiB0b2tlbnMKfSAgCgpjb25zdCBwYXJzZXIgPSB0b2tlbnMgPT4gewogIGxldCBjdXJyZW50ID0gMAoKICBjb25zdCBwZWVrID0gKCkgPT4gdG9rZW5zW2N1cnJlbnRdCiAgY29uc3QgcHJldiA9ICgpID0+IHRva2Vuc1tjdXJyZW50IC0gMV0KICBjb25zdCBtYXRjaCA9IHR5cGUgPT4gewogICAgaWYgKHBlZWsoKS50eXBlID09PSB0eXBlKSB7CiAgICAgIGN1cnJlbnQrKwogICAgICByZXR1cm4gdHJ1ZQogICAgfQogICAgcmV0dXJuIGZhbHNlCiAgfQoKICBjb25zdCBleHByID0gKCkgPT4gewogICAgcmV0dXJuIGFkZCgpCiAgfQoKICBjb25zdCBhZGQgPSAoKSA9PiB7CiAgICBsZXQgcmVzdWx0ID0gbXVsKCkKCiAgICB3aGlsZSAobWF0Y2goJ1BsdXMnKSB8fCBtYXRjaCgnTWludXMnKSkgewogICAgICBpZiAocHJldigpLnR5cGUgPT09ICdQbHVzJykgcmVzdWx0ID0gcmVzdWx0ICsgbXVsKCkKICAgICAgaWYgKHByZXYoKS50eXBlID09PSAnTWludXMnKSByZXN1bHQgPSByZXN1bHQgLSBtdWwoKQogICAgfQoKICAgIHJldHVybiByZXN1bHQKICB9CgogIGNvbnN0IG11bCA9ICgpID0+IHsKICAgIGxldCByZXN1bHQgPSBudW0oKQoKICAgIHdoaWxlIChtYXRjaCgnU3RhcicpIHx8IG1hdGNoKCdTbGFzaCcpKSB7CiAgICAgIGlmIChwcmV2KCkudHlwZSA9PT0gJ1N0YXInKSByZXN1bHQgPSByZXN1bHQgKiBudW0oKQogICAgICBpZiAocHJldigpLnR5cGUgPT09ICdTbGFzaCcpIHJlc3VsdCA9IHJlc3VsdCAvIG51bSgpCiAgICB9ICAgIAoKICAgIHJldHVybiByZXN1bHQKICB9CgogIGNvbnN0IG51bSA9ICgpID0+IHsKICAgIGlmIChtYXRjaCgnTnVtYmVyJykpIHsKICAgICAgcmV0dXJuIHByZXYoKS52YWx1ZQogICAgfQoKICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCAke3BlZWsoKS50eXBlfSB0b2tlbmApCiAgfQoKICByZXR1cm4gZXhwcigpCn0KCmNvbnNvbGUubG9nKCc0ICsgMyAqIDIgLSA0IC8gMiA9JywgcGFyc2VyKGxleGVyKCc0ICsgMyAqIDIgLSA0IC8gMicpKSkKY29uc29sZS5sb2coJzQgKiAzICsgMiAvIDIgLSA0ID0nLCBwYXJzZXIobGV4ZXIoJzQgKiAzICsgMiAvIDIgLSA0JykpKQ=="},"asBuffer":null},"loaded":true}}
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
const lexer = input => {
  let tokens = []
  let current = 0
  
  while (current < input.length) {
    let char = input[current]
    
    if (char === " ") {
      current++
      continue
    }

    if (char === "+") {
      tokens.push({ type: "Plus" })
      current++
      continue
    }

    if (char === "-") {
      tokens.push({ type: "Minus" })
      current++
      continue
    }

    if (char === "*") {
      tokens.push({ type: "Star" })
      current++
      continue
    }

    if (char === "/") {
      tokens.push({ type: "Slash" })
      current++
      continue
    }
    
    if (char === "(") {
      tokens.push({ type: "LeftParen" })
      current++
      continue
    }

    if (char === ")") {
      tokens.push({ type: "RightParen" })
      current++
      continue
    }

    if (/[0-9]/.test(char)) {
      let value = ''

      while (/[0-9]/.test(char)) {
        value += char
        current++
        char = input[current]
      }
      
      tokens.push({ type: "Number", value: parseInt(value, 10) })
      
      continue
    }

    throw new Error(`Unexpected char ${char}`)
  }

  tokens.push({ type: "End" })
  
  return tokens
}  

const parser = tokens => {
  let current = 0

  const peek = () => tokens[current]
  const prev = () => tokens[current - 1]
  const match = type => {
    if (peek().type === type) {
      current++
      return true
    }
    return false
  }

  const expr = () => {
    return add()
  }

  const add = () => {
    let result = mul()

    while (match('Plus') || match('Minus')) {
      if (prev().type === 'Plus') result = result + mul()
      if (prev().type === 'Minus') result = result - mul()
    }

    return result
  }

  const mul = () => {
    let result = num()

    while (match('Star') || match('Slash')) {
      if (prev().type === 'Star') result = result * num()
      if (prev().type === 'Slash') result = result / num()
    }    

    return result
  }

  const num = () => {
    if (match('Number')) {
      return prev().value
    }

    throw new Error(`Unexpected ${peek().type} token`)
  }

  return expr()
}

console.log('4 + 3 * 2 - 4 / 2 =', parser(lexer('4 + 3 * 2 - 4 / 2')))
console.log('4 * 3 + 2 / 2 - 4 =', parser(lexer('4 * 3 + 2 / 2 - 4')))
node v10.16.0