1
0
mirror of https://github.com/g012/l65.git synced 2024-06-11 10:29:27 +00:00

Added samepage/crosspage into lexer.

This commit is contained in:
g012 2017-09-09 16:49:10 +02:00
parent d991d818c1
commit 80085a969e
3 changed files with 82 additions and 35 deletions

View File

@ -2,6 +2,7 @@ local M = {}
local symbols={} M.symbols=symbols local symbols={} M.symbols=symbols
local locations={} M.locations=locations local locations={} M.locations=locations
local stats={} M.stats=stats
local byte_normalize = function(v) local byte_normalize = function(v)
if v < -128 or v > 255 then error("value out of byte range: " .. v) end if v < -128 or v > 255 then error("value out of byte range: " .. v) end
@ -20,13 +21,14 @@ local byte_emit = function(v, bin)
end end
local word_emit = function(v, bin) local word_emit = function(v, bin)
assert(v >=0 and v <= 0xffff) assert(v >=0 and v <= 0xffff)
bin[#bin+1] = 0xff & (v % 0x100) bin[#bin+1] = v & 0xff
bin[#bin+1] = 0xff & (v // 0x100) bin[#bin+1] = (v>>8) & 0xff
end end
M.link = function() M.link = function()
assert(not location.unused, "can't link twice") assert(not stats.unused, "can't link twice")
stats.unused = 0
for _,location in ipairs(locations) do for _,location in ipairs(locations) do
local sections = location.sections local sections = location.sections
@ -124,13 +126,14 @@ M.link = function()
local unused = 0 local unused = 0
for _,chunk in ipairs(location.chunks) do unused = unused + chunk.size - chunk.start end for _,chunk in ipairs(location.chunks) do unused = unused + chunk.size - chunk.start end
location.unused = unused location.unused = unused
stats.unused = stats.unused + unused
end end
end end
M.genbin = function(filler) M.genbin = function(filler)
if not filler then filler = 0xff end if not filler then filler = 0xff end
if not location.unused then M.link() end if not stats.unused then M.link() end
local bin = {} local bin = {}
local ins = table.insert local ins = table.insert
table.sort(locations, function(a,b) return a.start < b.start end) table.sort(locations, function(a,b) return a.start < b.start end)
@ -206,6 +209,13 @@ M.section = function(t)
end end
end end
M.samepage = function()
end
M.crosspage = function()
end
M.endpage = function()
end
M.byte = function(...) M.byte = function(...)
local data = {...} local data = {...}
for _,v in ipairs(data) do byte_emit(byte_normalize(v)) end for _,v in ipairs(data) do byte_emit(byte_normalize(v)) end

View File

@ -29,6 +29,7 @@ section "waitForIntim" --alt short syntax when no other option: @@waitForIntim ?
ldx #0b1101 ldx #0b1101
ldy #0xAB - 16 + 0b11011 & 3 | 6 ~ 0xf >> ~3 << 1 // 5 ldy #0xAB - 16 + 0b11011 & 3 | 6 ~ 0xf >> ~3 << 1 // 5
samepage
lda #0xac lda #0xac
lda #INTIM lda #INTIM
lda 0xbeef lda 0xbeef
@ -38,6 +39,7 @@ section "waitForIntim" --alt short syntax when no other option: @@waitForIntim ?
lda INTIM,y lda INTIM,y
lda (INTIM,x) lda (INTIM,x)
lda (INTIM),y lda (INTIM),y
end
asl asl
asl INTIM asl INTIM

97
l65.lua
View File

@ -33,7 +33,12 @@ local Keywords = lookupify{
}; };
-- 6502 opcodes -- 6502 opcodes
local Keywords_control = {
-- control keywords
'samepage', 'crosspage',
}
local Keywords_6502 = { local Keywords_6502 = {
-- opcodes
'adc', 'and', 'asl', 'bcc', 'bcs', 'beq', 'bit', 'bmi', 'adc', 'and', 'asl', 'bcc', 'bcs', 'beq', 'bit', 'bmi',
'bne', 'bpl', 'brk', 'bvc', 'bvs', 'clc', 'cld', 'cli', 'bne', 'bpl', 'brk', 'bvc', 'bvs', 'clc', 'cld', 'cli',
'clv', 'cmp', 'cpx', 'cpy', 'dec', 'dex', 'dey', 'eor', 'clv', 'cmp', 'cpx', 'cpy', 'dec', 'dex', 'dey', 'eor',
@ -50,6 +55,7 @@ local Keywords_6502 = {
local syntax6502_on local syntax6502_on
local function syntax6502(on) local function syntax6502(on)
syntax6502_on = on syntax6502_on = on
lookupify(Keywords_control, Keywords, not on)
lookupify(Keywords_6502, Keywords, not on) lookupify(Keywords_6502, Keywords, not on)
end end
syntax6502(true) syntax6502(true)
@ -245,7 +251,7 @@ local function LexLua(src)
while true do while true do
--check for eof --check for eof
if peek() == '' then if peek() == '' then
generateError("Expected `]"..string.rep('=', equalsCount).."]` near <eof>.", 3) generateError("Expected ']"..string.rep('=', equalsCount).."]' near <eof>.", 3)
end end
--check for the end --check for the end
@ -543,7 +549,7 @@ local function LexLua(src)
if contents then if contents then
toEmit = {Type = 'String', Data = all, Constant = contents} toEmit = {Type = 'String', Data = all, Constant = contents}
else else
generateError("Unexpected Symbol `"..c.."` in source.", 2) generateError("Unexpected Symbol '"..c.."' in source.", 2)
end end
end end
@ -683,7 +689,7 @@ local function ParseLua(src)
if line:sub(-1,-1) == '\n' then line = line:sub(1,-2) end if line:sub(-1,-1) == '\n' then line = line:sub(1,-2) end
lineNum = lineNum+1 lineNum = lineNum+1
if lineNum == tok:Peek().Line then if lineNum == tok:Peek().Line then
err = err..">> `"..line:gsub('\t',' ').."`\n" err = err..">> '"..line:gsub('\t',' ').."'\n"
for i = 1, tok:Peek().Char do for i = 1, tok:Peek().Char do
local c = line:sub(i,i) local c = line:sub(i,i)
if c == '\t' then if c == '\t' then
@ -717,7 +723,7 @@ local function ParseLua(src)
local function ParseFunctionArgsAndBody(scope, tokenList) local function ParseFunctionArgsAndBody(scope, tokenList)
local funcScope = CreateScope(scope) local funcScope = CreateScope(scope)
if not tok:ConsumeSymbol('(', tokenList) then if not tok:ConsumeSymbol('(', tokenList) then
return false, GenerateError("`(` expected.") return false, GenerateError("'(' expected.")
end end
--arg list --arg list
@ -731,17 +737,17 @@ local function ParseLua(src)
if tok:ConsumeSymbol(')', tokenList) then if tok:ConsumeSymbol(')', tokenList) then
break break
else else
return false, GenerateError("`)` expected.") return false, GenerateError("')' expected.")
end end
end end
elseif tok:ConsumeSymbol('...', tokenList) then elseif tok:ConsumeSymbol('...', tokenList) then
isVarArg = true isVarArg = true
if not tok:ConsumeSymbol(')', tokenList) then if not tok:ConsumeSymbol(')', tokenList) then
return false, GenerateError("`...` must be the last argument of a function.") return false, GenerateError("'...' must be the last argument of a function.")
end end
break break
else else
return false, GenerateError("Argument name or `...` expected") return false, GenerateError("Argument name or '...' expected")
end end
end end
@ -751,7 +757,7 @@ local function ParseLua(src)
--end --end
if not tok:ConsumeKeyword('end', tokenList) then if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("`end` expected after function body") return false, GenerateError("'end' expected after function body")
end end
local nodeFunc = {} local nodeFunc = {}
nodeFunc.AstType = 'Function' nodeFunc.AstType = 'Function'
@ -772,7 +778,7 @@ local function ParseLua(src)
local st, ex = ParseExpr(scope) local st, ex = ParseExpr(scope)
if not st then return false, ex end if not st then return false, ex end
if not tok:ConsumeSymbol(')', tokenList) then if not tok:ConsumeSymbol(')', tokenList) then
return false, GenerateError("`)` Expected.") return false, GenerateError("')' Expected.")
end end
if false then if false then
--save the information about parenthesized expressions somewhere --save the information about parenthesized expressions somewhere
@ -835,7 +841,7 @@ local function ParseLua(src)
local st, ex = ParseExpr(scope) local st, ex = ParseExpr(scope)
if not st then return false, ex end if not st then return false, ex end
if not tok:ConsumeSymbol(']', tokenList) then if not tok:ConsumeSymbol(']', tokenList) then
return false, GenerateError("`]` expected.") return false, GenerateError("']' expected.")
end end
local nodeIndex = {} local nodeIndex = {}
nodeIndex.AstType = 'IndexExpr' nodeIndex.AstType = 'IndexExpr'
@ -855,7 +861,7 @@ local function ParseLua(src)
if tok:ConsumeSymbol(')', tokenList) then if tok:ConsumeSymbol(')', tokenList) then
break break
else else
return false, GenerateError("`)` Expected.") return false, GenerateError("')' Expected.")
end end
end end
end end
@ -949,10 +955,10 @@ local function ParseLua(src)
return false, GenerateError("Key Expression Expected") return false, GenerateError("Key Expression Expected")
end end
if not tok:ConsumeSymbol(']', tokenList) then if not tok:ConsumeSymbol(']', tokenList) then
return false, GenerateError("`]` Expected") return false, GenerateError("']' Expected")
end end
if not tok:ConsumeSymbol('=', tokenList) then if not tok:ConsumeSymbol('=', tokenList) then
return false, GenerateError("`=` Expected") return false, GenerateError("'=' Expected")
end end
local st, value = ParseExpr(scope) local st, value = ParseExpr(scope)
if not st then if not st then
@ -971,7 +977,7 @@ local function ParseLua(src)
--we are a key --we are a key
local key = tok:Get(tokenList) local key = tok:Get(tokenList)
if not tok:ConsumeSymbol('=', tokenList) then if not tok:ConsumeSymbol('=', tokenList) then
return false, GenerateError("`=` Expected") return false, GenerateError("'=' Expected")
end end
local st, value = ParseExpr(scope) local st, value = ParseExpr(scope)
if not st then if not st then
@ -1015,7 +1021,7 @@ local function ParseLua(src)
elseif tok:ConsumeSymbol('}', tokenList) then elseif tok:ConsumeSymbol('}', tokenList) then
break break
else else
return false, GenerateError("`}` or table entry Expected") return false, GenerateError("'}' or table entry Expected")
end end
end end
v.Tokens = tokenList v.Tokens = tokenList
@ -1115,11 +1121,12 @@ local function ParseLua(src)
local tokenList = {} local tokenList = {}
local opcode_tok local opcode_tok
local function emit_call(func_name, args_expr) local function emit_call(func_name, args_expr, white)
if not white then white = opcode_tok.LeadingWhite end
local c,l = opcode_tok.Char, opcode_tok.Line local c,l = opcode_tok.Char, opcode_tok.Line
local op_var = { local op_var = {
AstType = 'VarExpr', Name = func_name, Variable = { IsGlobal=true, Name=func_name, Scope=CreateScope(scope) }, Tokens = { AstType = 'VarExpr', Name = func_name, Variable = { IsGlobal=true, Name=func_name, Scope=CreateScope(scope) }, Tokens = {
{ LeadingWhite = opcode_tok.LeadingWhite, Type='Ident', Data=func_name, Char=c, Line=l, Print=function() return '<Ident '..func_name..' >' end }, { LeadingWhite = white, Type='Ident', Data=func_name, Char=c, Line=l, Print=function() return '<Ident '..func_name..' >' end },
} }
} }
local exp_call = { local exp_call = {
@ -1156,6 +1163,34 @@ local function ParseLua(src)
stat = emit_call(is_local and 'label_local' or 'label', label_name) stat = emit_call(is_local and 'label_local' or 'label', label_name)
end end end end
-- new statements
if not stat then
local pagestat = function(fpage)
opcode_tok = tokenList[1]
local st, nodeBlock = ParseStatementList(scope)
if not st then return false, nodeBlock end
if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("'end' expected.")
end
local nodeDoStat = {}
nodeDoStat.AstType = 'DoStatement'
nodeDoStat.Body = nodeBlock
nodeDoStat.Tokens = tokenList
stat = nodeDoStat
tokenList[1].Data = 'do'
local space = {{ Char=opcode_tok.Char, Line=opcode_tok.Line, Data=' ', Type='Whitespace' }}
local opencall,closecall = emit_call(fpage,nil,space),emit_call('endpage',nil,space)
table.insert(nodeBlock.Body, 1, opencall)
table.insert(nodeBlock.Body, closecall)
end
if tok:ConsumeKeyword('samepage', tokenList) then pagestat('samepage')
elseif tok:ConsumeKeyword('crosspage', tokenList) then pagestat('crosspage')
end
end
-- 6502 opcodes -- 6502 opcodes
if not stat then if not stat then
for _,op in pairs(Keywords_6502) do for _,op in pairs(Keywords_6502) do
@ -1237,7 +1272,7 @@ local function ParseLua(src)
local st, nodeCond = ParseExpr(scope) local st, nodeCond = ParseExpr(scope)
if not st then return false, nodeCond end if not st then return false, nodeCond end
if not tok:ConsumeKeyword('then', tokenList) then if not tok:ConsumeKeyword('then', tokenList) then
return false, GenerateError("`then` expected.") return false, GenerateError("'then' expected.")
end end
local st, nodeBody = ParseStatementList(scope) local st, nodeBody = ParseStatementList(scope)
if not st then return false, nodeBody end if not st then return false, nodeBody end
@ -1258,7 +1293,7 @@ local function ParseLua(src)
--end --end
if not tok:ConsumeKeyword('end', tokenList) then if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("`end` expected.") return false, GenerateError("'end' expected.")
end end
nodeIfStat.Tokens = tokenList nodeIfStat.Tokens = tokenList
@ -1275,7 +1310,7 @@ local function ParseLua(src)
--do --do
if not tok:ConsumeKeyword('do', tokenList) then if not tok:ConsumeKeyword('do', tokenList) then
return false, GenerateError("`do` expected.") return false, GenerateError("'do' expected.")
end end
--body --body
@ -1284,7 +1319,7 @@ local function ParseLua(src)
--end --end
if not tok:ConsumeKeyword('end', tokenList) then if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("`end` expected.") return false, GenerateError("'end' expected.")
end end
--return --return
@ -1298,7 +1333,7 @@ local function ParseLua(src)
local st, nodeBlock = ParseStatementList(scope) local st, nodeBlock = ParseStatementList(scope)
if not st then return false, nodeBlock end if not st then return false, nodeBlock end
if not tok:ConsumeKeyword('end', tokenList) then if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("`end` expected.") return false, GenerateError("'end' expected.")
end end
local nodeDoStat = {} local nodeDoStat = {}
@ -1321,7 +1356,7 @@ local function ParseLua(src)
local st, startEx = ParseExpr(scope) local st, startEx = ParseExpr(scope)
if not st then return false, startEx end if not st then return false, startEx end
if not tok:ConsumeSymbol(',', tokenList) then if not tok:ConsumeSymbol(',', tokenList) then
return false, GenerateError("`,` Expected") return false, GenerateError("',' Expected")
end end
local st, endEx = ParseExpr(scope) local st, endEx = ParseExpr(scope)
if not st then return false, endEx end if not st then return false, endEx end
@ -1331,13 +1366,13 @@ local function ParseLua(src)
if not st then return false, stepEx end if not st then return false, stepEx end
end end
if not tok:ConsumeKeyword('do', tokenList) then if not tok:ConsumeKeyword('do', tokenList) then
return false, GenerateError("`do` expected") return false, GenerateError("'do' expected")
end end
-- --
local st, body = ParseStatementList(forScope) local st, body = ParseStatementList(forScope)
if not st then return false, body end if not st then return false, body end
if not tok:ConsumeKeyword('end', tokenList) then if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("`end` expected") return false, GenerateError("'end' expected")
end end
-- --
local nodeFor = {} local nodeFor = {}
@ -1362,7 +1397,7 @@ local function ParseLua(src)
varList[#varList+1] = forScope:CreateLocal(tok:Get(tokenList).Data) varList[#varList+1] = forScope:CreateLocal(tok:Get(tokenList).Data)
end end
if not tok:ConsumeKeyword('in', tokenList) then if not tok:ConsumeKeyword('in', tokenList) then
return false, GenerateError("`in` expected.") return false, GenerateError("'in' expected.")
end end
local generators = {} local generators = {}
local st, firstGenerator = ParseExpr(scope) local st, firstGenerator = ParseExpr(scope)
@ -1374,12 +1409,12 @@ local function ParseLua(src)
generators[#generators+1] = gen generators[#generators+1] = gen
end end
if not tok:ConsumeKeyword('do', tokenList) then if not tok:ConsumeKeyword('do', tokenList) then
return false, GenerateError("`do` expected.") return false, GenerateError("'do' expected.")
end end
local st, body = ParseStatementList(forScope) local st, body = ParseStatementList(forScope)
if not st then return false, body end if not st then return false, body end
if not tok:ConsumeKeyword('end', tokenList) then if not tok:ConsumeKeyword('end', tokenList) then
return false, GenerateError("`end` expected.") return false, GenerateError("'end' expected.")
end end
-- --
local nodeFor = {} local nodeFor = {}
@ -1397,7 +1432,7 @@ local function ParseLua(src)
if not st then return false, body end if not st then return false, body end
-- --
if not tok:ConsumeKeyword('until', tokenList) then if not tok:ConsumeKeyword('until', tokenList) then
return false, GenerateError("`until` expected.") return false, GenerateError("'until' expected.")
end end
-- FIX: Used to parse in parent scope -- FIX: Used to parse in parent scope
-- Now parses in repeat scope -- Now parses in repeat scope
@ -1483,7 +1518,7 @@ local function ParseLua(src)
end end
local label = tok:Get(tokenList).Data local label = tok:Get(tokenList).Data
if not tok:ConsumeSymbol('::', tokenList) then if not tok:ConsumeSymbol('::', tokenList) then
return false, GenerateError("`::` expected") return false, GenerateError("'::' expected")
end end
local nodeLabel = {} local nodeLabel = {}
nodeLabel.AstType = 'LabelStatement' nodeLabel.AstType = 'LabelStatement'
@ -1551,7 +1586,7 @@ local function ParseLua(src)
--equals --equals
if not tok:ConsumeSymbol('=', tokenList) then if not tok:ConsumeSymbol('=', tokenList) then
return false, GenerateError("`=` Expected.") return false, GenerateError("'=' Expected.")
end end
--rhs --rhs