parser/scanner: make codegen impl use own parser. closes #12857 (#12925)

pull/12928/head
joe-conigliaro 2021-12-22 04:48:06 +11:00 committed by GitHub
parent fc83f0bfd0
commit 07cf6d9f96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 22 deletions

View File

@ -83,6 +83,7 @@ mut:
comptime_if_cond bool comptime_if_cond bool
defer_vars []ast.Ident defer_vars []ast.Ident
should_abort bool // when too many errors/warnings/notices are accumulated, should_abort becomes true, and the parser should stop should_abort bool // when too many errors/warnings/notices are accumulated, should_abort becomes true, and the parser should stop
codegen_text string
} }
// for tests // for tests
@ -305,6 +306,13 @@ pub fn (mut p Parser) parse() &ast.File {
notices << p.scanner.notices notices << p.scanner.notices
} }
// codegen
if p.codegen_text.len > 0 && !p.pref.is_fmt {
ptext := 'module ' + p.mod.all_after('.') + p.codegen_text
codegen_file := parse_text(ptext, p.file_name, p.table, p.comments_mode, p.pref)
stmts << codegen_file.stmts
}
return &ast.File{ return &ast.File{
path: p.file_name path: p.file_name
path_base: p.file_base path_base: p.file_base
@ -396,6 +404,15 @@ pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences) []&
return files return files
} }
// codegen allows you to generate V code, so that it can be parsed,
// checked, markused, cgen-ed etc further, just like user's V code.
pub fn (mut p Parser) codegen(code string) {
$if debug_codegen ? {
eprintln('parser.codegen:\n $code')
}
p.codegen_text += '\n' + code
}
pub fn (mut p Parser) init_parse_fns() { pub fn (mut p Parser) init_parse_fns() {
// p.prefix_parse_fns = make(100, 100, sizeof(PrefixParseFn)) // p.prefix_parse_fns = make(100, 100, sizeof(PrefixParseFn))
// p.prefix_parse_fns[token.Kind.name] = parse_name // p.prefix_parse_fns[token.Kind.name] = parse_name
@ -3309,7 +3326,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
} }
} }
pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' } pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' }
p.scanner.codegen(' p.codegen('
// //
[inline] $pubfn ( e &$enum_name) is_empty() bool { return int(*e) == 0 } [inline] $pubfn ( e &$enum_name) is_empty() bool { return int(*e) == 0 }
[inline] $pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (int(flag))) != 0 } [inline] $pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (int(flag))) != 0 }

View File

@ -1460,27 +1460,6 @@ pub fn verror(s string) {
util.verror('scanner error', s) util.verror('scanner error', s)
} }
// codegen allows you to generate V code, so that it can be parsed,
// checked, markused, cgen-ed etc further, just like user's V code.
pub fn (mut s Scanner) codegen(newtext string) {
$if debug_codegen ? {
eprintln('scanner.codegen:\n $newtext')
}
if s.comments_mode == .skip_comments {
// Calling codegen makes sense only during normal compilation, since
// feeding code generated V code to vfmt or vdoc will cause them to
// output/document ephemeral stuff.
for s.all_tokens.len > 0 && s.all_tokens.last().kind == .eof {
s.all_tokens.delete_last()
}
s.text += newtext
old_tidx := s.tidx
s.tidx = s.all_tokens.len
s.scan_remaining_text()
s.tidx = old_tidx
}
}
fn (mut s Scanner) trace(fbase string, message string) { fn (mut s Scanner) trace(fbase string, message string) {
if s.file_base == fbase { if s.file_base == fbase {
println('> s.trace | ${fbase:-10s} | $message') println('> s.trace | ${fbase:-10s} | $message')