Skip to content

Instantly share code, notes, and snippets.

@coodoo

coodoo/dfa.js

Last active Aug 11, 2019
Embed
What would you like to do?
const T = {
INT: 'INT',
SIGN: 'SIGN',
DOT: 'DOT',
EXPO: 'EXPO',
SPACE: 'SPACE',
INVALID: 'INVALID',
EMPTY: 'EMPTY',
}
let currentState = 'EMPTY'
let last = null
let excludes = []
const trans = (event) => {
// console.log( '\ttrans:', event )
switch(currentState){
// 第一次進入
case 'EMPTY':
switch(event){
case 'EXPO':
currentState = 'PENDING'
break
default:
currentState = event
last = event
}
break
// 只要遇到一次 invalid,後面就都無效了
case 'SPACE':
case 'INVALID':
currentState = 'INVALID'
break
// 現在是數字的話
case 'INT':
switch(event){
case 'INT':
case 'DOT':
// debugger //
if(excludes.includes(event)){
currentState = 'INVALID'
}else{
currentState = event
}
break
case 'EXPO':
currentState = 'PENDING'
break
default:
currentState = 'INVALID'
}
last = event
break
// 現在是 SIGN
case 'SIGN':
switch(event){
case 'INT':
case 'EXPO':
currentState = event
break
default:
currentState = 'INVALID'
}
last = event
break
// 現在是 DOT
case 'DOT':
switch(event){
case 'INT':
case 'EXPO':
currentState = event
break
default:
currentState = 'INVALID'
}
last = event
break
// 現在是 expo
case 'EXPO':
switch(event){
case 'INT':
case 'SIGN':
currentState = event
break
default:
currentState = 'PENDING'
}
last = event
break
case 'PENDING':
switch(event){
case 'INT':
case 'SIGN':
// e3 已有 e,後面又出現 3,要檢查 e 前方是否有數字才算合格
currentState = last == 'INT' || last == 'EXPO' ? event : 'INVALID'
break
default:
currentState = 'INVALID'
}
last = event
break
default:
debugger
}
if(currentState === 'PENDING' || currentState === 'EXPO'){
excludes.push('DOT')
}
}
// 判斷字元的型別
const inputType = c => {
// console.log( '\tc=', c )
if(isNaN(+c) === false){
return 'INT'
} else if (c === '+' || c === '-') {
return 'SIGN'
} else if (c === '.') {
return 'DOT'
} else if (c === 'e') {
return 'EXPO'
} else if (c === ' ') {
return 'SPACE'
} else{
return 'INVALID'
}
}
// 進入點
const isNumber = input => {
input
.trim()
.split('')
.forEach(c => {
// console.log( '\nbefore: ', currentState )
trans(inputType(c))
// console.log( 'after: ', currentState )
})
return currentState
}
// 跑一堆測試,要全通過
const tests = [
'9e2.5',
'1e',
'1e3',
'e3',
'0',
' 0.1',
'abc',
'1 a',
'2e10',
'-90e3',
' 6e-1',
' 99e.25',
' 99e2.5',
'53.5e93',
' --6',
'-+3',
'95a54e53',
'12e+-34',
'1234',
'12+34',
'12-34',
'12e+34',
'12e34',
]
.forEach( str => {
currentState = 'EMPTY'
last = null
excludes = []
const res = isNumber(str)
const res2 = res == 'INVALID' || res == 'PENDING'
console.log( isNaN(Number(str)) == res2, str, Number(str), res )
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.