Upgrade to https://github.com/acornjs/acorn.git commit 84eda6bf
[jst.git] / src / tokentype.js
1 // ## Token types
2
3 // The assignment of fine-grained, information-carrying type objects
4 // allows the tokenizer to store the information it has about a
5 // token in a way that is very cheap for the parser to look up.
6
7 // All token type variables start with an underscore, to make them
8 // easy to recognize.
9
10 // The `beforeExpr` property is used to disambiguate between regular
11 // expressions and divisions. It is set on all token types that can
12 // be followed by an expression (thus, a slash after them would be a
13 // regular expression).
14 //
15 // The `startsExpr` property is used to check if the token ends a
16 // `yield` expression. It is set on all token types that either can
17 // directly start an expression (like a quotation mark) or can
18 // continue an expression (like the body of a string).
19 //
20 // `isLoop` marks a keyword as starting a loop, which is important
21 // to know when parsing a label, in order to allow or disallow
22 // continue jumps to that label.
23
24 export class TokenType {
25   constructor(label, conf = {}) {
26     this.label = label
27     this.keyword = conf.keyword
28     this.beforeExpr = !!conf.beforeExpr
29     this.startsExpr = !!conf.startsExpr
30     this.isLoop = !!conf.isLoop
31     this.isAssign = !!conf.isAssign
32     this.prefix = !!conf.prefix
33     this.postfix = !!conf.postfix
34     this.binop = conf.binop || null
35     this.updateContext = null
36   }
37 }
38
39 function binop(name, prec) {
40   return new TokenType(name, {beforeExpr: true, binop: prec})
41 }
42 const beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}
43
44 // Map keyword names to token types.
45
46 export const keywords = {}
47
48 // Succinct definitions of keyword token types
49 function kw(name, options = {}) {
50   options.keyword = name
51   return keywords[name] = new TokenType(name, options)
52 }
53
54 export const types = {
55   num: new TokenType("num", startsExpr),
56   regexp: new TokenType("regexp", startsExpr),
57   string: new TokenType("string", startsExpr),
58   name: new TokenType("name", startsExpr),
59   privateId: new TokenType("privateId", startsExpr),
60   eof: new TokenType("eof"),
61
62   // Punctuation token types.
63   bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
64   bracketR: new TokenType("]"),
65   braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
66   braceR: new TokenType("}"),
67   parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
68   parenR: new TokenType(")"),
69   comma: new TokenType(",", beforeExpr),
70   semi: new TokenType(";", beforeExpr),
71   colon: new TokenType(":", beforeExpr),
72   dot: new TokenType("."),
73   hash: new TokenType("#"), // Nick
74   question: new TokenType("?", beforeExpr),
75   questionDot: new TokenType("?."),
76   arrow: new TokenType("=>", beforeExpr),
77   template: new TokenType("template"),
78   invalidTemplate: new TokenType("invalidTemplate"),
79   ellipsis: new TokenType("...", beforeExpr),
80   backQuote: new TokenType("`", startsExpr),
81   dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
82
83   // Operators. These carry several kinds of properties to help the
84   // parser use them properly (the presence of these properties is
85   // what categorizes them as operators).
86   //
87   // `binop`, when present, specifies that this operator is a binary
88   // operator, and will refer to its precedence.
89   //
90   // `prefix` and `postfix` mark the operator as a prefix or postfix
91   // unary operator.
92   //
93   // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
94   // binary operators with a very low precedence, that should result
95   // in AssignmentExpression nodes.
96
97   eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
98   assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
99   incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
100   prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
101   logicalOR: binop("||", 1),
102   logicalAND: binop("&&", 2),
103   bitwiseOR: binop("|", 3),
104   bitwiseXOR: binop("^", 4),
105   bitwiseAND: binop("&", 5),
106   equality: binop("==/!=/===/!==", 6),
107   relational: binop("</>/<=/>=", 7),
108   bitShift: binop("<</>>/>>>", 8),
109   plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
110   modulo: binop("%", 10),
111   star: binop("*", 10),
112   slash: binop("/", 10),
113   starstar: new TokenType("**", {beforeExpr: true}),
114   coalesce: binop("??", 1),
115
116   // Keyword token types.
117   _break: kw("break"),
118   _case: kw("case", beforeExpr),
119   _catch: kw("catch"),
120   _continue: kw("continue"),
121   _debugger: kw("debugger"),
122   _default: kw("default", beforeExpr),
123   _do: kw("do", {isLoop: true, beforeExpr: true}),
124   _else: kw("else", beforeExpr),
125   _finally: kw("finally"),
126   _for: kw("for", {isLoop: true}),
127   _function: kw("function", startsExpr),
128   _if: kw("if"),
129   _return: kw("return", beforeExpr),
130   _switch: kw("switch"),
131   _throw: kw("throw", beforeExpr),
132   _try: kw("try"),
133   _var: kw("var"),
134   _const: kw("const"),
135   _while: kw("while", {isLoop: true}),
136   _with: kw("with"),
137   _new: kw("new", {beforeExpr: true, startsExpr: true}),
138   _this: kw("this", startsExpr),
139   _super: kw("super", startsExpr),
140   _class: kw("class", startsExpr),
141   _extends: kw("extends", beforeExpr),
142   _export: kw("export"),
143   _import: kw("import", startsExpr),
144   _null: kw("null", startsExpr),
145   _true: kw("true", startsExpr),
146   _false: kw("false", startsExpr),
147   _in: kw("in", {beforeExpr: true, binop: 7}),
148   _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
149   _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
150   _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
151   _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
152 }