@renatorib/

parser-v3

Nodejs

No description

fork
loading
Files
  • index.js

This Plugin Crashed!

Error: Error: must not create an existing file {"type":"CREATE_FILE","wid":"0.9286977642539258","path":"index.js","file":{"path":"index.js","content":{"asEncoding":{"base64":"Y29uc3QgbGV4ZXIgPSBpbnB1dCA9PiB7CiAgbGV0IHRva2VucyA9IFtdCiAgbGV0IGN1cnJlbnQgPSAwCiAgCiAgd2hpbGUgKGN1cnJlbnQgPCBpbnB1dC5sZW5ndGgpIHsKICAgIGxldCBjaGFyID0gaW5wdXRbY3VycmVudF0KICAgIAogICAgaWYgKGNoYXIgPT09ICIgIikgewogICAgICBjdXJyZW50KysKICAgICAgY29udGludWUKICAgIH0KCiAgICBpZiAoY2hhciA9PT0gIisiKSB7CiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogIlBsdXMiIH0pCiAgICAgIGN1cnJlbnQrKwogICAgICBjb250aW51ZQogICAgfQoKICAgIGlmIChjaGFyID09PSAiLSIpIHsKICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiAiTWludXMiIH0pCiAgICAgIGN1cnJlbnQrKwogICAgICBjb250aW51ZQogICAgfQoKICAgIGlmIChjaGFyID09PSAiKiIpIHsKICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiAiU3RhciIgfSkKICAgICAgY3VycmVudCsrCiAgICAgIGNvbnRpbnVlCiAgICB9CgogICAgaWYgKGNoYXIgPT09ICIvIikgewogICAgICB0b2tlbnMucHVzaCh7IHR5cGU6ICJTbGFzaCIgfSkKICAgICAgY3VycmVudCsrCiAgICAgIGNvbnRpbnVlCiAgICB9CiAgICAKICAgIGlmIChjaGFyID09PSAiKCIpIHsKICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiAiTGVmdFBhcmVuIiB9KQogICAgICBjdXJyZW50KysKICAgICAgY29udGludWUKICAgIH0KCiAgICBpZiAoY2hhciA9PT0gIikiKSB7CiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogIlJpZ2h0UGFyZW4iIH0pCiAgICAgIGN1cnJlbnQrKwogICAgICBjb250aW51ZQogICAgfQoKICAgIGlmICgvWzAtOV0vLnRlc3QoY2hhcikpIHsKICAgICAgbGV0IHZhbHVlID0gJycKCiAgICAgIHdoaWxlICgvWzAtOV0vLnRlc3QoY2hhcikpIHsKICAgICAgICB2YWx1ZSArPSBjaGFyCiAgICAgICAgY3VycmVudCsrCiAgICAgICAgY2hhciA9IGlucHV0W2N1cnJlbnRdCiAgICAgIH0KICAgICAgCiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogIk51bWJlciIsIHZhbHVlOiBwYXJzZUludCh2YWx1ZSwgMTApIH0pCiAgICAgIAogICAgICBjb250aW51ZQogICAgfQoKICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBjaGFyICR7Y2hhcn1gKQogIH0KCiAgdG9rZW5zLnB1c2goeyB0eXBlOiAiRW5kIiB9KQogIAogIHJldHVybiB0b2tlbnMKfSAgCgpjb25zdCBwYXJzZXIgPSB0b2tlbnMgPT4gewogIGxldCBjdXJyZW50ID0gMAoKICBjb25zdCBwZWVrID0gKCkgPT4gdG9rZW5zW2N1cnJlbnRdCiAgY29uc3QgcHJldiA9ICgpID0+IHRva2Vuc1tjdXJyZW50IC0gMV0KICBjb25zdCBtYXRjaCA9IHR5cGUgPT4gewogICAgaWYgKHBlZWsoKS50eXBlID09PSB0eXBlKSB7CiAgICAgIGN1cnJlbnQrKwogICAgICByZXR1cm4gdHJ1ZQogICAgfQogICAgcmV0dXJuIGZhbHNlCiAgfQoKICBjb25zdCBleHByID0gKCkgPT4gewogICAgcmV0dXJuIGFkZCgpCiAgfQoKICBjb25zdCBhZGQgPSAoKSA9PiB7CiAgICBsZXQgcmVzdWx0ID0gbXVsKCkKCiAgICB3aGlsZSAobWF0Y2goJ1BsdXMnKSB8fCBtYXRjaCgnTWludXMnKSkgewogICAgICBpZiAocHJldigpLnR5cGUgPT09ICdQbHVzJykgcmVzdWx0ID0gcmVzdWx0ICsgbXVsKCkKICAgICAgaWYgKHByZXYoKS50eXBlID09PSAnTWludXMnKSByZXN1bHQgPSByZXN1bHQgLSBtdWwoKQogICAgfQoKICAgIHJldHVybiByZXN1bHQKICB9CgogIGNvbnN0IG11bCA9ICgpID0+IHsKICAgIGxldCByZXN1bHQgPSB1bmEoKQoKICAgIHdoaWxlIChtYXRjaCgnU3RhcicpIHx8IG1hdGNoKCdTbGFzaCcpKSB7CiAgICAgIGlmIChwcmV2KCkudHlwZSA9PT0gJ1N0YXInKSByZXN1bHQgPSByZXN1bHQgKiB1bmEoKQogICAgICBpZiAocHJldigpLnR5cGUgPT09ICdTbGFzaCcpIHJlc3VsdCA9IHJlc3VsdCAvIHVuYSgpCiAgICB9ICAgIAoKICAgIHJldHVybiByZXN1bHQKICB9CgogIGNvbnN0IHVuYSA9ICgpID0+IHsKICAgIGlmIChtYXRjaCgnTWludXMnKSB8fCBtYXRjaCgnUGx1cycpKSB7CiAgICAgIGlmIChwcmV2KCkudHlwZSA9PT0gJ1BsdXMnKSByZXR1cm4gKyB1bmEoKQogICAgICBpZiAocHJldigpLnR5cGUgPT09ICdNaW51cycpIHJldHVybiAtIHVuYSgpCiAgICB9CgogICAgcmV0dXJuIG51bSgpCiAgfQoKICBjb25zdCBudW0gPSAoKSA9PiB7CiAgICBpZiAobWF0Y2goJ051bWJlcicpKSB7CiAgICAgIHJldHVybiBwcmV2KCkudmFsdWUKICAgIH0KCiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgJHtwZWVrKCkudHlwZX0gdG9rZW5gKQogIH0KCiAgcmV0dXJuIGV4cHIoKQp9Cgpjb25zb2xlLmxvZygnLTUgPScsIHBhcnNlcihsZXhlcignLTUnKSkpCmNvbnNvbGUubG9nKCctIC01ID0nLCBwYXJzZXIobGV4ZXIoJy0gLTUnKSkpCmNvbnNvbGUubG9nKCctIC0gLTUgPScsIHBhcnNlcihsZXhlcignLSAtIC01JykpKQpjb25zb2xlLmxvZygnLSAtIC0gLTUgPScsIHBhcnNlcihsZXhlcignLSAtIC0gLTUnKSkpCmNvbnNvbGUubG9nKCctIC0gLSAtNSArIDIgKiAtNSA9JywgcGFyc2VyKGxleGVyKCctIC0gLSAtNSArIDIgKiAtNScpKSkKY29uc29sZS5sb2coJysgKyArIDUgPScsIHBhcnNlcihsZXhlcignKyArICsgNScpKSkKY29uc29sZS5sb2coJy0gKyAtICsgNSA9JywgcGFyc2VyKGxleGVyKCctICsgLSArIDUnKSkp"},"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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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 = una()

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

    return result
  }

  const una = () => {
    if (match('Minus') || match('Plus')) {
      if (prev().type === 'Plus') return + una()
      if (prev().type === 'Minus') return - una()
    }

    return num()
  }

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

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

  return expr()
}

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