fork download
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4.  
  5. typedef enum { Error='e', First='F', Name='N', Text='T', Left='L', } Mode;
  6. typedef enum { Begin='B', End='E', } Type;
  7.  
  8. typedef struct Tag {
  9. char name;
  10. Type type;
  11. } Tag;
  12.  
  13. static inline int
  14. istarch(int ch) {
  15. return (isalnum(ch) || ch == ' ');
  16. }
  17.  
  18. static Tag*
  19. read_tag_name(Tag* tag, char** src) {
  20. Mode m = First;
  21. char* p = *src;
  22.  
  23. tag->name = 0;
  24.  
  25. for (; ; ++p) {
  26. char ch = *p;
  27. if (ch == '\0')
  28. goto error;
  29.  
  30. switch (m) {
  31. default: goto error; break;
  32. case First:
  33. if (isalpha(ch)) {
  34. tag->name = ch;
  35. tag->type = Begin;
  36. m = Name;
  37. } else if (ch == '/') {
  38. tag->type = End;
  39. m = Name;
  40. } else {
  41. goto error;
  42. }
  43. break;
  44. case Name:
  45. if (isalpha(ch)) {
  46. tag->name = ch;
  47. } else if (ch == '>') {
  48. if (!tag->name)
  49. goto error;
  50. goto success;
  51. }
  52. break;
  53. }
  54. }
  55. error:
  56. *src = p;
  57. return NULL;
  58. success:
  59. *src = p;
  60. return tag;
  61. }
  62.  
  63. static Tag*
  64. read_tag(Tag* btag, char** src) {
  65. Mode m = First;
  66. char* p = *src;
  67.  
  68. if (!btag)
  69. goto error;
  70.  
  71. for (; ; ++p) {
  72. char ch = *p;
  73. if (ch == '\0') {
  74. goto error;
  75. }
  76.  
  77. switch (m) {
  78. default: goto error; break;
  79. case First:
  80. if (istarch(ch)) m = Text;
  81. else if (ch == '<') m = Left;
  82. break;
  83. case Text:
  84. if (ch == '<') m = Left;
  85. break;
  86. case Left: {
  87. Tag tmp;
  88. if (!read_tag_name(&tmp, &p)) {
  89. goto error;
  90. }
  91. if (tmp.name == 'a' && btag->name == 'b') {
  92. goto error;
  93. }
  94. if (tmp.name == btag->name && tmp.type == End) {
  95. goto success;
  96. }
  97. if (!read_tag(&tmp, &p)) {
  98. goto error;
  99. }
  100. m = First;
  101. } break;
  102. }
  103. }
  104. error:
  105. *src = p;
  106. return NULL;
  107. success:
  108. *src = p;
  109. return btag;
  110. }
  111.  
  112. static int
  113. parse(char* src) {
  114. Mode m = First;
  115. char* p = src;
  116.  
  117. for (; ; ++p) {
  118. char ch = *p;
  119. if (ch == '\0') {
  120. if (m == Text || m == First)
  121. goto success;
  122. goto error;
  123. }
  124.  
  125. switch (m) {
  126. default: goto error; break;
  127. case First:
  128. if (istarch(ch)) m = Text;
  129. else if (ch == '<') m = Left;
  130. else goto error;
  131. break;
  132. case Text:
  133. if (ch == '<') m = Left;
  134. break;
  135. case Left: {
  136. Tag t;
  137. if (!read_tag(read_tag_name(&t, &p), &p)) {
  138. goto error;
  139. }
  140. m = First;
  141. } break;
  142. }
  143. }
  144. error:
  145. return 0;
  146. success:
  147. return 1;
  148. }
  149.  
  150. int main(void) {
  151. char buf[1024];
  152.  
  153. while (fgets(buf, sizeof buf, stdin)) {
  154. size_t len = strlen(buf);
  155. if (buf[len-1] == '\n')
  156. buf[len-1] = '\0';
  157. printf("%d '%s'\n", parse(buf), buf);
  158. }
  159. return 0;
  160. }
  161.  
Success #stdin #stdout 0s 2012KB
stdin
<a>ruby<b>php</b>python</a><a><b></b></a><a></a>
<a>ruby<b>php</b>python</a><a></b></a><a></a>
<a>ruby<b>php</b>python</a><a><b></a><a></a>
<a>ruby<b>php</b>python</a><a><b></b></a><a>
vvvc<a>ruby<b>php</b>python</a><a><b></b></a><a></a> 
stdout
1 '<a>ruby<b>php</b>python</a><a><b></b></a><a></a>'
0 '<a>ruby<b>php</b>python</a><a></b></a><a></a>'
0 '<a>ruby<b>php</b>python</a><a><b></a><a></a>'
0 '<a>ruby<b>php</b>python</a><a><b></b></a><a>'
1 'vvvc<a>ruby<b>php</b>python</a><a><b></b></a><a></a> '