Skip to content

Instantly share code, notes, and snippets.

@liyonghelpme
Created December 22, 2019 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liyonghelpme/7a8d89ba40b5bae4f3c63b8d32cb6034 to your computer and use it in GitHub Desktop.
Save liyonghelpme/7a8d89ba40b5bae4f3c63b8d32cb6034 to your computer and use it in GitHub Desktop.
//digitSeq e digit
enum NodeType {
Enter,
Digit,
Exponent,
End,
BeforePoint,
Point,
AfterPoint,
}
enum TokenType {
Num,
Sign,
Point,
Exp,
Empty,
Unknown,
EOF, //读取结束状态
}
enum ParseResult {
OK,
Error,
}
class Result {
ret : ParseResult = null
nextToken : number = null
reason : string = null
}
let list = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
//0-9
function IsNumber(c : string){
// return !isNaN(Number(c))
for(let i = 0; i < list.length; i++){
if(list[i] === c) return true
}
return false
}
function IsSign(c : string) {
return c == "-" || c == "+"
}
function IsPoint(c : string) {
return c == "."
}
function IsE(c : string) {
return c == "e"
}
function IsEmpty(c : string) {
return c == " " || c == "\t"
}
function GetTokenType(c : string) {
if(IsNumber(c)) return TokenType.Num
if(IsSign(c)) return TokenType.Sign
if(IsE(c)) return TokenType.Exp
if(IsPoint(c)) return TokenType.Point
if(IsEmpty(c)) return TokenType.Empty
return TokenType.Unknown
}
class StateMachine {
curNode : StateNode
curStep : number = 0
input : string = null
result : boolean
allNodes : Map<NodeType, StateNode> = new Map()
Init() {}
// MoveNext() {
// if(this.curNode.next != null){
// this.curNode = this.curNode.next
// }else {
// console.log("Error:NoNext:", )
// }
// }
MoveTo(s : StateNode) {
this.curNode = s
}
Parse(inp : string) {
inp += " "
this.input = inp
// console.log("parse", this.input)
for(this.curStep = 0; this.curStep < this.input.length;){
// console.log(this.curNode, this.curStep)
let ret = this.curNode.Read(this.input, this.curStep)
// console.log(this.curNode.type, this.curNode.constructor.name, ret)
if(ret.ret == ParseResult.Error) {
// console.log(ret.reason, this.curStep)
// console.log(this.curNode.constructor.name)
return false
}
this.curStep = ret.nextToken
}
if(this.curNode.type != NodeType.End){
// console.log("not find number")
return false
}
return true
}
MoveToType(nt : NodeType) {
this.curNode = this.allNodes.get(nt)
}
AddNode(s : StateNode) {
this.allNodes.set(s.type, s)
s.mac = this
}
GetNode( t : NodeType)
{
return this.allNodes.get(t)
}
}
class StateNode {
type : NodeType = null
// next : StateNode = null
mac : StateMachine = null
// subNodes : Map<NodeType, StateNode> = new Map()
parent : StateNode
constructor(machine : StateMachine) {
this.mac = machine
}
Read(input :string, i : number){
let ret = new Result()
ret.nextToken = i
ret.ret = ParseResult.OK
return ret
}
// AddChild(s : StateNode){
// this.subNodes.set(s.type, s)
// s.parent = this
// s.mac = this.mac
// }
// GetChild(nt : NodeType) {
// return this.subNodes.get(nt)
// }
}
class EnterNode extends StateNode {
Read(input :string, i : number) {
let c = input[i]
let tk = GetTokenType(c)
let ret = new Result()
// console.log("Enter", c, tk)
switch(tk) {
case TokenType.Empty:
ret.nextToken = i+1
ret.ret = ParseResult.OK
return ret
case TokenType.Sign:
case TokenType.Num:
case TokenType.Point:
this.mac.MoveToType(NodeType.Digit)
ret.nextToken = i
ret.ret = ParseResult.OK
return ret
case TokenType.Exp:
default:
ret.nextToken = 0
ret.ret = ParseResult.Error
ret.reason = "exp or unknown token"
return ret
}
}
}
class BeforePoint extends StateNode {
hasSign : boolean = false
readNum : string[] = []
firstNum : number = null
numCount : number = 0
Read(input :string, i : number){
let ret = new Result()
let c = input[i]
switch(GetTokenType(c)){
case TokenType.Sign:
if(this.readNum.length > 0) {
ret.ret = ParseResult.Error
ret.reason = "Read Sign"
return ret
}
this.hasSign = true
this.readNum.push(c)
ret.ret = ParseResult.OK
ret.nextToken = i+1
return ret
case TokenType.Num:
this.readNum.push(c)
ret.ret = ParseResult.OK
ret.nextToken = i+1
if(this.firstNum == null){
this.firstNum = Number(c)
}
this.numCount++
// if(this.firstNum == 0 && this.numCount > 1) {
// ret.ret = ParseResult.Error
// ret.reason = "first zero"
// return ret
// }
return ret
case TokenType.Point:
//检查数字完整性
// if(this.readNum.length > 0) {
// if(this.numCount > 1 && this.firstNum == 0){
// ret.ret = ParseResult.Error
// ret.reason = "first Zero"
// return ret
// }
// }
ret.ret = ParseResult.OK
ret.nextToken = i
// this.mac.MoveTo(this.parent.GetChild(NodeType.Point))
this.mac.MoveToType(NodeType.Point)
return ret
// if(this.readNum.length)
case TokenType.Exp:
if(this.numCount == 0){
ret.reason = "No Number"
ret.ret = ParseResult.Error
return ret
}
this.mac.MoveToType(NodeType.Exponent)
ret.ret = ParseResult.OK
ret.nextToken = i+1
return ret
//读取结束
case TokenType.Empty:
// if(this.readNum.length == 0){
// ret.reason = "Error No Num"
// ret.ret = ParseResult.Error
// return ret
// }
// if(this.readNum.length == 1 && this.hasSign){
// ret.reason = "Error No Num"
// ret.ret = ParseResult.Error
// return ret
// }
if(this.numCount == 0) {
ret.reason = "Error No Num"
ret.ret = ParseResult.Error
return ret
}
// if(this.numCount > 1 && this.firstNum == 0){
// ret.ret = ParseResult.Error
// ret.reason = "first Zero"
// return ret
// }
ret.ret = ParseResult.OK
ret.nextToken = i+1
this.mac.MoveToType(NodeType.End)
return ret
default:
ret.reason = "Error Token"
ret.ret = ParseResult.Error
return ret
}
}
}
class PointNode extends StateNode {
hasPoint : boolean = false
Read(input :string, i : number){
let ret = new Result()
let c = input[i]
switch(GetTokenType(c)){
case TokenType.Point:
this.hasPoint = true
ret.ret = ParseResult.OK
ret.nextToken = i+1
this.mac.MoveToType(NodeType.AfterPoint)
return ret
default:
ret.ret = ParseResult.Error
ret.reason = "Not Find Point"
return ret
}
}
}
class AfterNode extends StateNode {
nums : number[] = []
numCount : number = 0
Read(input :string, i : number){
let ret = new Result()
let c = input[i]
switch(GetTokenType(c)){
case TokenType.Num:
ret.ret = ParseResult.OK
ret.nextToken = i+1
this.nums.push(Number(c))
this.numCount++
return ret
case TokenType.Exp: {
let bt = this.mac.GetNode(NodeType.BeforePoint) as BeforePoint
if(bt.numCount == 0 && this.numCount == 0) {
ret.ret = ParseResult.Error
ret.reason = "no numb"
return ret
}
ret.ret = ParseResult.OK
ret.nextToken = i+1
this.mac.MoveToType(NodeType.Exponent)
return ret
}
case TokenType.Empty: {
let bt = this.mac.GetNode(NodeType.BeforePoint) as BeforePoint
if(bt.numCount == 0 && this.numCount == 0) {
ret.ret = ParseResult.Error
ret.reason = "no numb"
return ret
}
ret.ret = ParseResult.OK
ret.nextToken = i+1
this.mac.MoveToType(NodeType.End)
return ret
}
default:
ret.ret = ParseResult.Error
ret.reason = "Error Token"
return ret
}
}
}
//digit Exp
//Sign number point number
class DigitNode extends StateNode {
Read(input :string, i : number){
let ret = new Result()
let c = input[i]
switch(GetTokenType(c)){
case TokenType.Num:
case TokenType.Sign:
// this.mac.MoveTo(this.GetChild(NodeType.BeforePoint))
this.mac.MoveToType(NodeType.BeforePoint)
ret.nextToken = i
ret.ret = ParseResult.OK
return ret
case TokenType.Point:
// this.mac.MoveTo(this.GetChild(NodeType.Point))
this.mac.MoveToType(NodeType.Point)
ret.nextToken = i
ret.ret = ParseResult.OK
return ret
case TokenType.Exp:
case TokenType.Empty:
default:
ret.ret = ParseResult.Error
ret.reason = "Empty"
return ret
}
}
}
class ExponentNode extends StateNode {
hasSign : boolean
nums : string[] = []
numCount : number = 0
Read(input :string, i : number){
let ret = new Result()
let c = input[i]
switch(GetTokenType(c)){
case TokenType.Sign:
if(this.nums.length > 0) {
ret.reason = "sign error"
ret.ret = ParseResult.Error
return ret
}
this.hasSign = true
this.nums.push(c)
ret.nextToken = i+1
ret.ret = ParseResult.OK
return ret
case TokenType.Num:
this.nums.push(c)
ret.nextToken = i+1
ret.ret = ParseResult.OK
this.numCount++
return ret
case TokenType.Empty:
if(this.numCount == 0) {
ret.ret = ParseResult.Error
ret.reason = "NO Number"
return ret
}
this.mac.MoveToType(NodeType.End)
ret.nextToken = i+1
ret.ret = ParseResult.OK
return ret
default:
ret.reason = "token error"
ret.ret = ParseResult.Error
return ret
}
}
}
class EndNode extends StateNode {
Read(input :string, i : number){
let ret = new Result()
let c = input[i]
switch(GetTokenType(c)){
case TokenType.Empty:
ret.nextToken = i+1
ret.ret = ParseResult.OK
return ret
default:
ret.reason = "error token"
ret.ret = ParseResult.Error
return ret
}
}
}
//浮点数判定Node
class FloatMachine extends StateMachine {
Init() {
let n = new EnterNode(this)
n.type = NodeType.Enter
this.curNode = n
let n1 = new DigitNode(this)
n1.type = NodeType.Digit
let n3 = new BeforePoint(this)
n3.type = NodeType.BeforePoint
// n1.AddChild(n3)
let n4 = new PointNode(this)
n4.type = NodeType.Point
// n1.AddChild(n4)
let n5 = new AfterNode(this)
n5.type = NodeType.AfterPoint
// n1.AddChild(n5)
let n2 = new ExponentNode(this)
n2.type = NodeType.Exponent
// n3.next = n4
// n4.next = n5
// n5.next = n2
// n.next = n1
// n1.next = n2
let n6 = new EndNode(this)
n6.type = NodeType.End
this.AddNode(n1)
this.AddNode(n2)
this.AddNode(n3)
this.AddNode(n4)
this.AddNode(n5)
this.AddNode(n6)
}
}
class CheckNum {
input : string
Check() {
let m = new FloatMachine()
m.Init()
return m.Parse(this.input)
}
}
var test = [
// "0",
// " 0.1 ",
// "abc" ,
// "1 a" ,
// "2e10" ,
// " -90e3 " ,
// " 1e",
// "e3" ,
// " 6e-1" ,
// " 99e2.5 " ,
// "53.5e93",
// " --6 " ,
// "-+3" ,
// "95a54e53" ,
".",
"01",
]
test.forEach(element => {
var ip = element
var cn = new CheckNum()
cn.input = ip
console.log(ip, cn.Check())
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment