r - tokeniser.go
		
     1  package r
     2  
     3  import (
     4  	"io"
     5  	"strconv"
     6  
     7  	"vimagination.zapto.org/parser"
     8  )
     9  
    10  const (
    11  	whitespace      = "\t\v\f \u00a0\ufeff" // Tab, Vertical Tab, Form Feed, Space, No-break space, ZeroWidth No-Break Space, https://262.ecma-international.org/11.0/#table-32
    12  	lineTerminators = "\n\r\u2028\u2029"    // Semi-Colon, Line Feed, Carriage Return, Line Separator, Paragraph Separator, https://262.ecma-international.org/11.0/#table-33
    13  	octalDigit      = "01234567"
    14  	decimalDigit    = "0123456789"
    15  	hexDigit        = "0123456789abcdefABCDEF"
    16  	identifierStart = "ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvwxyz"
    17  	identifierCont  = "_.0123456789ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvwxyz"
    18  )
    19  
    20  // TokenType IDs
    21  const (
    22  	TokenWhitespace parser.TokenType = iota
    23  	TokenLineTerminator
    24  	TokenWhitespaceLineTerminator
    25  	TokenExpressionTerminator
    26  	TokenComment
    27  	TokenStringLiteral
    28  	TokenNumericLiteral
    29  	TokenIntegerLiteral
    30  	TokenComplexLiteral
    31  	TokenBooleanLiteral
    32  	TokenNull
    33  	TokenNA
    34  	TokenIdentifier
    35  	TokenKeyword
    36  	TokenEllipsis
    37  	TokenOperator
    38  	TokenSpecialOperator
    39  	TokenGrouping
    40  )
    41  
    42  // SetTokeniser sets the initial tokeniser state of a parser.Tokeniser.
    43  //
    44  // Used if you want to manually tokeniser R source code.
    45  func SetTokeniser(t *parser.Tokeniser) *parser.Tokeniser {
    46  	t.TokeniserState(new(rTokeniser).expression)
    47  
    48  	return t
    49  }
    50  
    51  type rTokeniser struct {
    52  	state []byte
    53  }
    54  
    55  func (r *rTokeniser) lastState() byte {
    56  	if len(r.state) == 0 {
    57  		return 0
    58  	}
    59  
    60  	d := r.state[len(r.state)-1]
    61  
    62  	r.state = r.state[:len(r.state)-1]
    63  
    64  	return d
    65  }
    66  
    67  func (r *rTokeniser) expression(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
    68  	if t.Peek() == -1 {
    69  		if len(r.state) != 0 {
    70  			return t.ReturnError(io.ErrUnexpectedEOF)
    71  		}
    72  
    73  		return t.Done()
    74  	}
    75  
    76  	if t.Accept(whitespace) {
    77  		t.AcceptRun(whitespace)
    78  
    79  		return t.Return(TokenWhitespace, r.expression)
    80  	}
    81  
    82  	if t.Accept(lineTerminators) {
    83  		if len(r.state) > 0 && r.state[len(r.state)-1] != '}' {
    84  			return t.Return(TokenWhitespaceLineTerminator, r.expression)
    85  		}
    86  
    87  		return t.Return(TokenLineTerminator, r.expression)
    88  	}
    89  
    90  	if t.Accept("#") {
    91  		t.ExceptRun(lineTerminators)
    92  
    93  		return t.Return(TokenComment, r.expression)
    94  	}
    95  
    96  	if t.Accept(identifierStart) {
    97  		return r.identifier(t)
    98  	}
    99  
   100  	if c := t.Peek(); c == '"' || c == '\'' {
   101  		return r.string(t)
   102  	} else if c == '.' || c >= '0' && c <= '9' {
   103  		return r.number(t)
   104  	}
   105  
   106  	return r.operator(t)
   107  }
   108  
   109  func (r *rTokeniser) string(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
   110  	quote := t.Next()
   111  
   112  	chars := string(quote) + "\\"
   113  
   114  	for {
   115  		switch t.ExceptRun(chars) {
   116  		case quote:
   117  			t.Next()
   118  
   119  			return t.Return(TokenStringLiteral, r.expression)
   120  		case '\\':
   121  			t.Next()
   122  
   123  			switch t.Peek() {
   124  			case '\'', '"', 'n', 'r', 't', 'b', 'a', 'f', 'v', '\\':
   125  				t.Next()
   126  			case '0', '1', '2', '3', '4', '5', '6', '7':
   127  				t.Next()
   128  
   129  				if !t.Accept(octalDigit) || !t.Accept(octalDigit) {
   130  					return t.ReturnError(ErrInvalidString)
   131  				}
   132  			case 'x':
   133  				t.Next()
   134  
   135  				if !t.Accept(hexDigit) || !t.Accept(hexDigit) {
   136  					return t.ReturnError(ErrInvalidString)
   137  				}
   138  			case 'u':
   139  				t.Next()
   140  
   141  				brace := t.Accept("{")
   142  
   143  				if !t.Accept(hexDigit) {
   144  					return t.ReturnError(ErrInvalidString)
   145  				}
   146  
   147  				if brace {
   148  					t.Accept(hexDigit)
   149  					t.Accept(hexDigit)
   150  					t.Accept(hexDigit)
   151  
   152  					if !t.Accept("}") {
   153  						return t.ReturnError(ErrInvalidString)
   154  					}
   155  				} else if !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) {
   156  					return t.ReturnError(ErrInvalidString)
   157  				}
   158  			case 'U':
   159  				t.Next()
   160  
   161  				brace := t.Accept("{")
   162  
   163  				if !t.Accept(hexDigit) {
   164  					return t.ReturnError(ErrInvalidString)
   165  				}
   166  
   167  				if brace {
   168  					t.Accept(hexDigit)
   169  					t.Accept(hexDigit)
   170  					t.Accept(hexDigit)
   171  					t.Accept(hexDigit)
   172  					t.Accept(hexDigit)
   173  					t.Accept(hexDigit)
   174  					t.Accept(hexDigit)
   175  
   176  					if !t.Accept("}") {
   177  						return t.ReturnError(ErrInvalidString)
   178  					}
   179  				} else if !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) {
   180  					return t.ReturnError(ErrInvalidString)
   181  				}
   182  			default:
   183  				return t.ReturnError(ErrInvalidString)
   184  			}
   185  		case -1:
   186  			return t.ReturnError(ErrInvalidString)
   187  		}
   188  	}
   189  }
   190  
   191  func (r *rTokeniser) number(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
   192  	if t.Accept(".") {
   193  		if !t.Accept(decimalDigit) {
   194  			return r.ellipsisOrIdentifier(t)
   195  		}
   196  
   197  		return r.float(t, decimalDigit)
   198  	}
   199  
   200  	digits := decimalDigit
   201  
   202  	if t.Accept("0") {
   203  		if t.Accept("x") {
   204  			digits = hexDigit
   205  
   206  			if !t.Accept(digits) {
   207  				return t.ReturnError(ErrInvalidNumber)
   208  			}
   209  		}
   210  	}
   211  
   212  	t.AcceptRun(digits)
   213  
   214  	if t.Accept("L") {
   215  		return t.Return(TokenIntegerLiteral, r.expression)
   216  	} else if t.Accept("i") {
   217  		return t.Return(TokenComplexLiteral, r.expression)
   218  	} else if t.Accept(".") {
   219  		return r.float(t, digits)
   220  	}
   221  
   222  	return r.exponential(t, digits)
   223  }
   224  
   225  func (r *rTokeniser) float(t *parser.Tokeniser, digits string) (parser.Token, parser.TokenFunc) {
   226  	if digits == hexDigit && !t.Accept(digits) {
   227  		return t.ReturnError(ErrInvalidNumber)
   228  	}
   229  
   230  	t.AcceptRun(digits)
   231  
   232  	if t.Accept("L") {
   233  		return t.Return(TokenIntegerLiteral, r.expression)
   234  	} else if t.Accept("i") {
   235  		return t.Return(TokenComplexLiteral, r.expression)
   236  	}
   237  
   238  	return r.exponential(t, digits)
   239  }
   240  
   241  func (r *rTokeniser) exponential(t *parser.Tokeniser, digits string) (parser.Token, parser.TokenFunc) {
   242  	e := "eE"
   243  
   244  	if digits == hexDigit {
   245  		e = "pP"
   246  	}
   247  
   248  	if t.Accept(e) {
   249  		t.Accept("+-")
   250  
   251  		if !t.Accept(digits) {
   252  			return t.ReturnError(ErrInvalidNumber)
   253  		}
   254  
   255  		t.AcceptRun(digits)
   256  	}
   257  
   258  	if t.Accept("L") {
   259  		return t.Return(TokenIntegerLiteral, r.expression)
   260  	} else if t.Accept("i") {
   261  		return t.Return(TokenComplexLiteral, r.expression)
   262  	}
   263  
   264  	return t.Return(TokenNumericLiteral, r.expression)
   265  }
   266  
   267  func (r *rTokeniser) ellipsisOrIdentifier(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
   268  	if t.Accept(".") {
   269  		if t.Accept(".") {
   270  			if !t.Accept(identifierCont) {
   271  				return t.Return(TokenEllipsis, r.expression)
   272  			}
   273  		} else if t.Accept(decimalDigit) {
   274  			t.AcceptRun(decimalDigit)
   275  
   276  			if !t.Accept(identifierCont) {
   277  				return t.Return(TokenEllipsis, r.expression)
   278  			}
   279  		}
   280  	}
   281  
   282  	return r.identifier(t)
   283  }
   284  
   285  func (r *rTokeniser) identifier(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
   286  	t.AcceptRun(identifierCont)
   287  
   288  	tk := parser.Token{Type: TokenIdentifier, Data: t.Get()}
   289  
   290  	switch tk.Data {
   291  	case "NULL":
   292  		tk.Type = TokenNull
   293  	case "TRUE", "FALSE":
   294  		tk.Type = TokenBooleanLiteral
   295  	case "Inf", "NaN":
   296  		tk.Type = TokenNumericLiteral
   297  	case "NA", "NA_character_", "NA_integer_", "NA_real_", "NA_complex_":
   298  		tk.Type = TokenNA
   299  	case "if", "else", "repeat", "while", "function", "for", "in", "next", "break":
   300  		tk.Type = TokenKeyword
   301  	}
   302  
   303  	return tk, r.expression
   304  }
   305  
   306  func (r *rTokeniser) operator(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
   307  	if t.Accept(";,") {
   308  		return t.Return(TokenExpressionTerminator, r.expression)
   309  	} else if t.Accept("+*/^~$@?") {
   310  	} else if t.Accept(">=!") {
   311  		t.Accept("=")
   312  	} else if t.Accept("-") {
   313  		t.Accept(">")
   314  		t.Accept(">")
   315  	} else if t.Accept("<") {
   316  		if t.Accept("<") && !t.Accept("-") {
   317  			return t.ReturnError(ErrInvalidOperator)
   318  		} else {
   319  			t.Accept("=-")
   320  		}
   321  	} else if t.Accept("%") {
   322  		for ; t.Peek() != '%' && strconv.IsPrint(t.Peek()); t.Next() {
   323  		}
   324  
   325  		if !t.Accept("%") {
   326  			return t.ReturnError(ErrInvalidOperator)
   327  		}
   328  
   329  		return t.Return(TokenSpecialOperator, r.expression)
   330  	} else if t.Accept(":") {
   331  		t.Accept(":")
   332  	} else if t.Accept("&") {
   333  		t.Accept("&")
   334  	} else if t.Accept("|") {
   335  		t.Accept("|>")
   336  	} else if t.Accept("[") {
   337  		if t.Accept("[") {
   338  			r.state = append(r.state, '#')
   339  		} else {
   340  			r.state = append(r.state, ']')
   341  		}
   342  
   343  		return t.Return(TokenGrouping, r.expression)
   344  	} else if t.Accept("(") {
   345  		r.state = append(r.state, ')')
   346  
   347  		return t.Return(TokenGrouping, r.expression)
   348  	} else if t.Accept("{") {
   349  		r.state = append(r.state, '}')
   350  
   351  		return t.Return(TokenGrouping, r.expression)
   352  	} else if t.Accept("]") {
   353  		if g := r.lastState(); g == '#' {
   354  			if !t.Accept("]") {
   355  				return t.ReturnError(ErrInvalidCharacter)
   356  			}
   357  		} else if g != ']' {
   358  			return t.ReturnError(ErrInvalidCharacter)
   359  		}
   360  
   361  		return t.Return(TokenGrouping, r.expression)
   362  	} else if t.Accept(")") {
   363  		if r.lastState() != ')' {
   364  			return t.ReturnError(ErrInvalidCharacter)
   365  		}
   366  
   367  		return t.Return(TokenGrouping, r.expression)
   368  	} else if t.Accept("}") {
   369  		if r.lastState() != '}' {
   370  			return t.ReturnError(ErrInvalidCharacter)
   371  		}
   372  
   373  		return t.Return(TokenGrouping, r.expression)
   374  	} else {
   375  		return t.ReturnError(ErrInvalidCharacter)
   376  	}
   377  
   378  	return t.Return(TokenOperator, r.expression)
   379  }
   380