syntax.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 Rule struct {
  10. Id Id
  11. Nullable bool
  12. Branches [] Branch
  13. }
  14. type Branch struct {
  15. Parts [] Part
  16. }
  17. type Part struct {
  18. Id Id
  19. PartType PartType
  20. Required bool
  21. }
  22. type PartType int
  23. const (
  24. MatchKeyword PartType = iota
  25. MatchToken
  26. Recursive
  27. )
  28. func GetPartType (name string) PartType {
  29. var is_keyword = strings.HasPrefix(name, "@") && len(name) > 1
  30. if is_keyword {
  31. return MatchKeyword
  32. } else {
  33. var t = name[0:1]
  34. if strings.ToUpper(t) == t {
  35. // the name starts with capital letter
  36. return MatchToken
  37. } else {
  38. // the name starts with small letter
  39. return Recursive
  40. }
  41. }
  42. }
  43. func EscapePartName (name string) string {
  44. if strings.HasPrefix(name, "_") && EscapeMap[name] != "" {
  45. return EscapeMap[name]
  46. } else {
  47. return name
  48. }
  49. }
  50. var Id2Name [] string
  51. var Name2Id map[string] Id
  52. var Id2Keyword map[Id] []rune
  53. var Rules map[Id] Rule
  54. func __Allocate () {
  55. Id2Name = make([]string, 0, 1000)
  56. Name2Id = make(map[string]Id)
  57. Id2Keyword = make(map[Id][]rune)
  58. Rules = make(map[Id]Rule)
  59. }
  60. func __AssignId2Name (name string) Id {
  61. var existing, exists = Name2Id[name]
  62. if exists {
  63. return existing
  64. }
  65. var id = Id(len(Id2Name))
  66. Name2Id[name] = id
  67. Id2Name = append(Id2Name, name)
  68. return id
  69. }
  70. func __AssignId2Tokens () {
  71. for _, token := range Tokens {
  72. __AssignId2Name(token.Name)
  73. }
  74. }
  75. func __AssignId2Keywords () {
  76. for _, name := range ConditionalKeywords {
  77. var keyword = []rune(strings.TrimLeft(name, "@"))
  78. if len(keyword) == 0 { panic("empty keyword") }
  79. var id = __AssignId2Name(name)
  80. Id2Keyword[id] = keyword
  81. }
  82. }
  83. func __AssignId2Rules () {
  84. for _, def := range SyntaxDefinition {
  85. var t = strings.Split(def, "=")
  86. var u = strings.Trim(t[0], " ")
  87. var rule_name = strings.TrimRight(u, "?")
  88. __AssignId2Name(rule_name)
  89. }
  90. }
  91. func __ParseRules () {
  92. for _, def := range SyntaxDefinition {
  93. var pivot = strings.Index(def, "=")
  94. if (pivot == -1) { panic(def + ": invalid rule: missing =") }
  95. // name = ...
  96. var str_name = strings.Trim(def[:pivot], " ")
  97. var name = strings.TrimRight(str_name, "?")
  98. var nullable = strings.HasSuffix(str_name, "?")
  99. var id, exists = Name2Id[name]
  100. if (!exists) { panic("undefined rule name: " + name) }
  101. // ... = branches
  102. var str_branches = strings.Trim(def[pivot+1:], " ")
  103. if (str_branches == "") { panic(name + ": missing rule definition") }
  104. var strlist_branches = strings.Split(str_branches, " | ")
  105. var n_branches = len(strlist_branches)
  106. var strlist2_branches = make([][]string, n_branches)
  107. for i, str_branch := range strlist_branches {
  108. strlist2_branches[i] = strings.Split(str_branch, " ")
  109. }
  110. var branches = make([]Branch, n_branches)
  111. for i, strlist_branch := range strlist2_branches {
  112. var num_parts = len(strlist_branch)
  113. branches[i].Parts = make([]Part, num_parts)
  114. if num_parts > MAX_NUM_PARTS {
  115. panic(name + ": too many parts")
  116. }
  117. for j, str_part := range strlist_branch {
  118. // check if valid
  119. if str_part == "" {
  120. panic("redundant blank in definition of " + str_name)
  121. }
  122. // extract part name
  123. var required = strings.HasSuffix(str_part, "!")
  124. var part_name = strings.TrimRight(str_part, "!")
  125. part_name = EscapePartName(part_name)
  126. // add to list if it is a keyword
  127. var part_type = GetPartType(part_name)
  128. var id, exists = Name2Id[part_name]
  129. if (!exists) { panic("undefined part: " + part_name) }
  130. branches[i].Parts[j] = Part {
  131. Id: id, Required: required, PartType: part_type,
  132. }
  133. }
  134. }
  135. Rules[id] = Rule {
  136. Branches: branches,
  137. Nullable: nullable,
  138. Id: id,
  139. }
  140. }
  141. }
  142. func __Init () interface{} {
  143. __Allocate()
  144. __AssignId2Tokens()
  145. __AssignId2Keywords()
  146. __AssignId2Rules()
  147. __ParseRules()
  148. return nil
  149. }
  150. var _ = __Init()