셀프호스팅에 손대기 전의 강제 함수다. 아픈 자리를 전부 건드린다: R4 아래의 토큰 구조체, 태그드 유니온, 진단 출력, 유닛 경계. 토큰은 자기가 나온 글자를 담지 않는다. R4 가 대여를 집합 저장소에서 막으므로, 어디서 시작해 얼마나 긴지를 적고 소스는 옆에서 같이 다닌다. 위치도 &mut usize 로 옆에서 다닌다 -- 슬라이스와 함께 구조체에 들어갈 수 없기 때문이다. 이것이 R11 이 말하는 모양이고, 쓸 수 있다. first keyword unit @1 / number 42 @3 / text "hi" @3 / arrow -> @5 keyword 6 name 7 number 1 text 1 punct 15 / total 30 길에서 고친 것: - binding.Type.Variant 가 안 풀렸다. 유닛 경계 이름 조회가 심볼만 보고 타입을 보지 않았다. - 문자열 const 전역이 빈 슬라이스로 나갔다. 포인터는 링커만 아는 수라서 바이트에 구멍을 두고 링커가 채우게 한다. - exec.py 가 OUTPUT 마커를 여러 개 적어도 마지막 하나만 검사했다. 고치자마자 readfile 의 낡은 기대가 드러났다. run.py 217/217, exec.py 27/27.
62 lines
1.9 KiB
Plaintext
62 lines
1.9 KiB
Plaintext
// EXIT:0
|
|
// OUTPUT:first keyword unit @1
|
|
// OUTPUT:number 42 @3
|
|
// OUTPUT:text "hi" @3
|
|
// OUTPUT:arrow -> @5
|
|
// OUTPUT:keyword 6 name 7 number 1 text 1 punct 15
|
|
// OUTPUT:total 30
|
|
unit main;
|
|
import std.io;
|
|
import tok;
|
|
import scan;
|
|
|
|
// The Ferro lexer, written in Ferro. This is the shape a self-hosted `fec`
|
|
// would take: read a source, hand back tokens, say where each came from.
|
|
|
|
const SOURCE: str = "unit demo;\n\nfn answer() { let n = 42; let s = \"hi\"; }\n// a comment\nfn arrow() -> i32 { return n; }\n";
|
|
|
|
fn main() -> i32 {
|
|
var at: usize = 0;
|
|
var line: usize = 1;
|
|
var keywords: usize = 0;
|
|
var names: usize = 0;
|
|
var numbers: usize = 0;
|
|
var texts: usize = 0;
|
|
var puncts: usize = 0;
|
|
var total: usize = 0;
|
|
var first: bool = true;
|
|
while true {
|
|
let t: tok.Token = scan.next(SOURCE, &mut at, &mut line);
|
|
if t.kind == tok.Kind.End { break; }
|
|
total = total + 1;
|
|
if first {
|
|
@print("first {} {} @{}\n", tok.name_of(t.kind),
|
|
tok.text(SOURCE, t), t.line);
|
|
first = false;
|
|
}
|
|
match t.kind {
|
|
Keyword => { keywords = keywords + 1; }
|
|
Name => { names = names + 1; }
|
|
Number => {
|
|
numbers = numbers + 1;
|
|
@print("number {} @{}\n", tok.text(SOURCE, t), t.line);
|
|
}
|
|
Text => {
|
|
texts = texts + 1;
|
|
@print("text {} @{}\n", tok.text(SOURCE, t), t.line);
|
|
}
|
|
Punct => {
|
|
puncts = puncts + 1;
|
|
if t.len == 2 {
|
|
@print("arrow {} @{}\n", tok.text(SOURCE, t), t.line);
|
|
}
|
|
}
|
|
_ => { @print("unexpected {}\n", tok.name_of(t.kind)); }
|
|
}
|
|
}
|
|
@print("keyword {} name {} number {} text {} punct {}\n",
|
|
keywords, names, numbers, texts, puncts);
|
|
@print("total {}\n", total);
|
|
return 0;
|
|
}
|