syntax.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package syntax
  2. import "strings"
  3. const MAX_NUM_PARTS = 20
  4. type Id int
  5. type Token struct {
  6. Name string
  7. Pattern Regexp
  8. }
  9. type LeftRight int
  10. const (
  11. Left LeftRight = iota
  12. Right
  13. )
  14. type Operator struct {
  15. Match string
  16. Priority int
  17. Assoc LeftRight
  18. Lazy bool
  19. CanRedef bool
  20. }
  21. type Rule struct {
  22. Id Id
  23. Emptable bool
  24. Branches []Branch
  25. }
  26. type Branch struct {
  27. Parts []Part
  28. }
  29. type PartType int
  30. const (
  31. MatchKeyword PartType = iota
  32. MatchToken
  33. Recursive
  34. )
  35. type Part struct {
  36. Id Id
  37. Partype PartType
  38. Required bool
  39. }
  40. func GetPartType (name string) PartType {
  41. var is_keyword = strings.HasPrefix(name, "@") && len(name) > 1
  42. if is_keyword {
  43. return MatchKeyword
  44. } else {
  45. var t = name[0:1]
  46. if strings.ToUpper(t) == t {
  47. // the name starts with capital letter
  48. return MatchToken
  49. } else {
  50. // the name starts with small letter
  51. return Recursive
  52. }
  53. }
  54. }
  55. func EscapePartName (name string) string {
  56. if strings.HasPrefix(name, "_") && EscapeMap[name] != "" {
  57. return EscapeMap[name]
  58. } else {
  59. return name
  60. }
  61. }
  62. var Id2Name []string
  63. var Name2Id map[string]Id
  64. var Id2Keyword map[Id][]rune
  65. var Id2Operator map[Id]Operator
  66. var Rules map[Id]Rule
  67. // var RootName string
  68. func Allocate () {
  69. Id2Name = make([]string, 0, 1000)
  70. Name2Id = make(map[string]Id)
  71. Id2Keyword = make(map[Id][]rune)
  72. Id2Operator = make(map[Id]Operator)
  73. Rules = make(map[Id]Rule)
  74. }
  75. func AssignId2Name (name string) Id {
  76. // TODO: check repeat
  77. var id = Id(len(Id2Name))
  78. Name2Id[name] = id
  79. Id2Name = append(Id2Name, name)
  80. return id
  81. }
  82. func AssignId2Extra () {
  83. for _, token_name := range Extra {
  84. AssignId2Name(token_name)
  85. }
  86. }
  87. func AssignId2Tokens () {
  88. for _, token := range Tokens {
  89. AssignId2Name(token.Name)
  90. }
  91. }
  92. func AssignId2Keywords () {
  93. for _, name := range Keywords {
  94. var keyword = []rune(strings.TrimLeft(name, "@"))
  95. if len(keyword) == 0 { panic("empty keyword") }
  96. var id = AssignId2Name(name)
  97. Id2Keyword[id] = keyword
  98. }
  99. }
  100. func AssignId2Rules () {
  101. for _, def := range SyntaxDefinition {
  102. var t = strings.Split(def, "=")
  103. var u = strings.Trim(t[0], " ")
  104. var rule_name = strings.TrimRight(u, "?")
  105. AssignId2Name(rule_name)
  106. /*
  107. if (i == 0) {
  108. RootName = rule_name
  109. }
  110. */
  111. }
  112. }
  113. func ProcessOperatorInfo () {
  114. for _, operator := range Operators {
  115. var id, exists = Name2Id[operator.Match]
  116. if !exists {
  117. panic("match for operator " + operator.Match + " does not exist")
  118. }
  119. if operator.Priority < 0 {
  120. // priority must be non-negative
  121. panic("operator " + operator.Match + " has a negative priority")
  122. }
  123. for _, redefinable := range RedefinableOperators {
  124. if operator.Match == redefinable {
  125. operator.CanRedef = true
  126. break
  127. }
  128. }
  129. Id2Operator[id] = operator
  130. }
  131. }
  132. func ParseRules () {
  133. for _, def := range SyntaxDefinition {
  134. var pivot = strings.Index(def, "=")
  135. if (pivot == -1) { panic(def + ": invalid rule: missing =") }
  136. // name = ...
  137. var str_name = strings.Trim(def[:pivot], " ")
  138. var name = strings.TrimRight(str_name, "?")
  139. var emptable = strings.HasSuffix(str_name, "?")
  140. var id, exists = Name2Id[name]
  141. if (!exists) { panic("undefined rule name: " + name) }
  142. // ... = branches
  143. var str_branches = strings.Trim(def[pivot+1:], " ")
  144. if (str_branches == "") { panic(name + ": missing rule definition") }
  145. var strlist_branches = strings.Split(str_branches, " | ")
  146. var n_branches = len(strlist_branches)
  147. var strlist2_branches = make([][]string, n_branches)
  148. for i, str_branch := range strlist_branches {
  149. strlist2_branches[i] = strings.Split(str_branch, " ")
  150. }
  151. var branches = make([]Branch, n_branches)
  152. for i, strlist_branch := range strlist2_branches {
  153. var num_parts = len(strlist_branch)
  154. branches[i].Parts = make([]Part, num_parts)
  155. if num_parts > MAX_NUM_PARTS { panic(name + ": too many parts") }
  156. for j, str_part := range strlist_branch {
  157. // check if valid
  158. if str_part == "" {
  159. panic("redundant blank in definition of " + str_name)
  160. }
  161. // extract part name
  162. var required = strings.HasSuffix(str_part, "!")
  163. var part_name = strings.TrimRight(str_part, "!")
  164. part_name = EscapePartName(part_name)
  165. // add to list if it is a keyword
  166. var part_type = GetPartType(part_name)
  167. var id, exists = Name2Id[part_name]
  168. if (!exists) { panic("undefined part: " + part_name) }
  169. branches[i].Parts[j] = Part {
  170. Id: id, Required: required, Partype: part_type,
  171. }
  172. }
  173. }
  174. Rules[id] = Rule {
  175. Branches: branches, Emptable: emptable, Id: id,
  176. }
  177. }
  178. }
  179. func Init () {
  180. Allocate()
  181. AssignId2Extra()
  182. AssignId2Tokens()
  183. AssignId2Keywords()
  184. AssignId2Rules()
  185. ProcessOperatorInfo()
  186. ParseRules()
  187. }