github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/internal/pattern/inst.go (about)

     1  package pattern
     2  
     3  import (
     4  	"fmt"
     5  	"unicode/utf8"
     6  )
     7  
     8  type opCode rune
     9  
    10  const (
    11  	opMatch opCode = iota + utf8.MaxRune + 1
    12  	opJmp
    13  	opSplit
    14  	opBeginSave
    15  	opEndSave
    16  	opCapture
    17  
    18  	opAny
    19  	opLetter
    20  	opControl
    21  	opDigit
    22  	opGraphic
    23  	opLower
    24  	opPunct
    25  	opSpace
    26  	opUpper
    27  	opAlphaNum
    28  	opHexDigit
    29  	opZero
    30  
    31  	opNotLetter
    32  	opNotControl
    33  	opNotDigit
    34  	opNotGraphic
    35  	opNotLower
    36  	opNotPunct
    37  	opNotSpace
    38  	opNotUpper
    39  	opNotAlphaNum
    40  	opNotHexDigit
    41  	opNotZero
    42  
    43  	opSet
    44  	opFrontier
    45  	opBalance
    46  )
    47  
    48  type instruction struct {
    49  	op opCode
    50  	x  int
    51  	y  int
    52  }
    53  
    54  func (inst instruction) String() string {
    55  	switch inst.op {
    56  	case opMatch:
    57  		return fmt.Sprintf("op: match")
    58  	case opJmp:
    59  		return fmt.Sprintf("op: jmp, x: %d", inst.x)
    60  	case opSplit:
    61  		return fmt.Sprintf("op: split, x: %d, y: %d", inst.x, inst.y)
    62  	case opBeginSave:
    63  		return fmt.Sprintf("op: begin save, x: %d", inst.x)
    64  	case opEndSave:
    65  		return fmt.Sprintf("op: end save, x: %d", inst.x)
    66  	case opCapture:
    67  		return fmt.Sprintf("op: capture")
    68  
    69  	case opAny:
    70  		return fmt.Sprintf("op: any")
    71  	case opLetter:
    72  		return fmt.Sprintf("op: letter")
    73  	case opControl:
    74  		return fmt.Sprintf("op: control")
    75  	case opDigit:
    76  		return fmt.Sprintf("op: digit")
    77  	case opGraphic:
    78  		return fmt.Sprintf("op: graphic")
    79  	case opLower:
    80  		return fmt.Sprintf("op: lower")
    81  	case opPunct:
    82  		return fmt.Sprintf("op: punctuation")
    83  	case opSpace:
    84  		return fmt.Sprintf("op: space")
    85  	case opUpper:
    86  		return fmt.Sprintf("op: upper")
    87  	case opAlphaNum:
    88  		return fmt.Sprintf("op: word")
    89  	case opHexDigit:
    90  		return fmt.Sprintf("op: hex digit")
    91  	case opZero:
    92  		return fmt.Sprintf("op: zero")
    93  
    94  	case opNotLetter:
    95  		return fmt.Sprintf("op: not letter")
    96  	case opNotControl:
    97  		return fmt.Sprintf("op: not control")
    98  	case opNotDigit:
    99  		return fmt.Sprintf("op: not digit")
   100  	case opNotGraphic:
   101  		return fmt.Sprintf("op: not graphic")
   102  	case opNotLower:
   103  		return fmt.Sprintf("op: not lower")
   104  	case opNotPunct:
   105  		return fmt.Sprintf("op: not punctuation")
   106  	case opNotSpace:
   107  		return fmt.Sprintf("op: not space")
   108  	case opNotUpper:
   109  		return fmt.Sprintf("op: not upper")
   110  	case opNotAlphaNum:
   111  		return fmt.Sprintf("op: not word")
   112  	case opNotHexDigit:
   113  		return fmt.Sprintf("op: not hex digit")
   114  	case opNotZero:
   115  		return fmt.Sprintf("op: not zero")
   116  
   117  	case opSet:
   118  		return fmt.Sprintf("op: set")
   119  	case opFrontier:
   120  		return fmt.Sprintf("op: frontier")
   121  	case opBalance:
   122  		return fmt.Sprintf("op: balance, x: %c, y: %c", rune(inst.x), rune(inst.y))
   123  
   124  	default:
   125  		if 0 <= inst.op && inst.op <= utf8.MaxRune {
   126  			return fmt.Sprintf("op: %c", inst.op)
   127  		}
   128  
   129  		return fmt.Sprintf("op: unknown")
   130  	}
   131  }
   132  
   133  func instChar(r rune) instruction {
   134  	return instruction{op: opCode(r)}
   135  }
   136  
   137  func instAny() instruction {
   138  	return instruction{op: opAny}
   139  }
   140  
   141  func instClassOrEscChar(r rune) (instruction, bool) {
   142  	switch r {
   143  	case eos:
   144  		return instruction{}, false
   145  	case 'a':
   146  		return instruction{op: opLetter}, true
   147  	case 'A':
   148  		return instruction{op: opNotLetter}, true
   149  	case 'c':
   150  		return instruction{op: opControl}, true
   151  	case 'C':
   152  		return instruction{op: opNotControl}, true
   153  	case 'd':
   154  		return instruction{op: opDigit}, true
   155  	case 'D':
   156  		return instruction{op: opNotDigit}, true
   157  	case 'g':
   158  		return instruction{op: opGraphic}, true
   159  	case 'G':
   160  		return instruction{op: opNotGraphic}, true
   161  	case 'l':
   162  		return instruction{op: opLower}, true
   163  	case 'L':
   164  		return instruction{op: opNotLower}, true
   165  	case 'p':
   166  		return instruction{op: opPunct}, true
   167  	case 'P':
   168  		return instruction{op: opNotPunct}, true
   169  	case 's':
   170  		return instruction{op: opSpace}, true
   171  	case 'S':
   172  		return instruction{op: opNotSpace}, true
   173  	case 'u':
   174  		return instruction{op: opUpper}, true
   175  	case 'U':
   176  		return instruction{op: opNotUpper}, true
   177  	case 'w':
   178  		return instruction{op: opAlphaNum}, true
   179  	case 'W':
   180  		return instruction{op: opNotAlphaNum}, true
   181  	case 'x':
   182  		return instruction{op: opHexDigit}, true
   183  	case 'X':
   184  		return instruction{op: opNotHexDigit}, true
   185  	case 'z':
   186  		return instruction{op: opZero}, true
   187  	case 'Z':
   188  		return instruction{op: opNotZero}, true
   189  	default:
   190  		if !isAlphaNum(r) {
   191  			return instChar(r), true
   192  		}
   193  		return instruction{}, false
   194  	}
   195  }
   196  
   197  func instMatch() instruction {
   198  	return instruction{
   199  		op: opMatch,
   200  	}
   201  }
   202  
   203  // x: next instruction, higher precedence than y
   204  // y: next instruction
   205  func instSplit(x, y int) instruction {
   206  	return instruction{
   207  		op: opSplit,
   208  		x:  x,
   209  		y:  y,
   210  	}
   211  }
   212  
   213  // x: next instruction
   214  func instJmp(x int) instruction {
   215  	return instruction{
   216  		op: opJmp,
   217  		x:  x,
   218  	}
   219  }
   220  
   221  // x: depth
   222  func instBeginSave(x int) instruction {
   223  	return instruction{
   224  		op: opBeginSave,
   225  		x:  x,
   226  	}
   227  }
   228  
   229  // x: depth
   230  // y: 1 if the paren is empty
   231  func instEndSave(x, y int) instruction {
   232  	return instruction{
   233  		op: opEndSave,
   234  		x:  x,
   235  		y:  y,
   236  	}
   237  }
   238  
   239  // x: capture number
   240  func instCapture(x int) instruction {
   241  	return instruction{
   242  		op: opCapture,
   243  		x:  x,
   244  	}
   245  }
   246  
   247  func instSet(x int) instruction {
   248  	return instruction{
   249  		op: opSet,
   250  		x:  x,
   251  	}
   252  }
   253  
   254  func instFrontier(x int) instruction {
   255  	return instruction{
   256  		op: opFrontier,
   257  		x:  x,
   258  	}
   259  }
   260  
   261  func instBalance(x, y int) instruction {
   262  	return instruction{
   263  		op: opBalance,
   264  		x:  x,
   265  		y:  y,
   266  	}
   267  }