|
1 |
|
2 //:load matcher.scala |
|
3 |
|
4 // some regular expressions |
|
5 val SYM = RANGE("""ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz_""") |
|
6 val DIGIT = RANGE("0123456789") |
|
7 val ID = SEQ(PLUS(SYM)) ~ STAR(ALT(SYM, DIGIT)) |
|
8 |
|
9 val BTAG = SEQS("<", WORD, ">") |
|
10 val ETAG = SEQS("</", WORD, ">") |
|
11 |
|
12 val WHITESPACE = PLUS(RANGE(" \n")) |
|
13 |
|
14 // for classifying the strings that have been recognised |
|
15 abstract class Token |
|
16 case object T_WHITESPACE extends Token |
|
17 case class T_WORD(s: String) extends Token |
|
18 case class T_ETAG(s: String) extends Token |
|
19 case class T_BTAG(s: String) extends Token |
|
20 case class T_NT(s: String, rhs: List[Token]) extends Token |
|
21 |
|
22 val lexing_rules: List[Rule[Token]] = |
|
23 List((BTAG, (s) => T_BTAG(s.mkString)), |
|
24 (ETAG, (s) => T_ETAG(s.mkString)), |
|
25 (WORD, (s) => T_WORD(s.mkString)), |
|
26 (WHITESPACE, (s) => T_WHITESPACE)) |
|
27 |
|
28 // the tokenizer |
|
29 val T = Tokenizer(lexing_rules) |
|
30 |
|
31 // width for printing |
|
32 val WIDTH = 60 |
|
33 |
|
34 |
|
35 def interpret(ts: List[Token], c: Int, ctr: List[String]) : Unit= ts match { |
|
36 case Nil => println(Console.RESET) |
|
37 case T_WHITESPACE::rest => print(Console.RESET + " "); interpret(rest, c + 1, ctr) |
|
38 case T_WORD(s)::rest => { |
|
39 val newstr = Console.RESET + ctr.reverse.mkString + s |
|
40 if (c + s.length < WIDTH) { |
|
41 print(newstr); |
|
42 interpret(rest, c + s.length, ctr) |
|
43 } |
|
44 else { |
|
45 print("\n" + newstr) |
|
46 interpret(rest, s.length, ctr) |
|
47 } |
|
48 } |
|
49 case T_BTAG("<p>")::rest => print("\n"); interpret(rest, 0, ctr) |
|
50 case T_ETAG("</p>")::rest => print("\n"); interpret(rest, 0, ctr) |
|
51 case T_BTAG("<b>")::rest => interpret(rest, c, Console.BOLD :: ctr) |
|
52 case T_BTAG("<a>")::rest => interpret(rest, c, Console.UNDERLINED :: ctr) |
|
53 case T_BTAG("<cyan>")::rest => interpret(rest, c, Console.CYAN :: ctr) |
|
54 case T_BTAG("<red>")::rest => interpret(rest, c, Console.RED :: ctr) |
|
55 case T_BTAG("<blink>")::rest => interpret(rest, c, Console.BLINK :: ctr) |
|
56 case T_ETAG(_)::rest => interpret(rest, c, ctr.tail) |
|
57 case _::rest => interpret(rest, c, ctr) |
|
58 } |
|
59 |
|
60 interpret(T.fromFile("test.html"), 0, Nil) |