Skip to content

Commit 83f1981

Browse files
committed
perf(dbg): new MI LALR(1)
1 parent 11cc794 commit 83f1981

2 files changed

Lines changed: 181 additions & 1 deletion

File tree

‎debugger/src/debugger/debugger.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from pydantic import BaseModel
88

9-
from debugger import mion
9+
from . import mion
1010

1111
from .base_debugger import BaseDebugger
1212

‎debugger/src/debugger/mi.py‎

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
from textwrap import dedent
2+
from lark import Lark, Transformer
3+
from pydantic import BaseModel
4+
5+
grammar = r"""
6+
?start: lines
7+
8+
lines: line*
9+
line: (_out_of_band_record | result_record | PROMPT) NL
10+
PROMPT: "(GDB)"
11+
NL: "\r" | "\n" | "\r\n"
12+
13+
result_record: TN "^" rc comma_results
14+
rc: "done" -> done
15+
| "running" -> running
16+
| "connected" -> connected
17+
| "error" -> error
18+
| "exit" -> exit
19+
20+
_out_of_band_record: _async_record | _stream_record
21+
22+
_async_record: exec_async_output | status_async_output | notify_async_output
23+
exec_async_output: TN "+" "stopped" comma_results
24+
status_async_output: TN "*" "stopped" comma_results
25+
notify_async_output: TN "=" "stopped" comma_results
26+
27+
_stream_record: console_stream_output | target_stream_output | log_stream_output
28+
console_stream_output: "~" C_STR
29+
target_stream_output: "@" C_STR
30+
log_stream_output: "&" C_STR
31+
32+
TN: /[0-9]+/
33+
comma_results: ("," result)*
34+
35+
result: KEY "=" _value
36+
KEY: /[_a-zA_Z][_a-zA_Z\d]*/
37+
_value: C_STR | tuple | list
38+
tuple: "{}" | "{" result ("," result)* "}"
39+
list: "[]" | "[" _value ("," _value)* "]" | "[" list_kv ("," list_kv)* "]"
40+
list_kv: KEY "=" _value
41+
42+
C_STR: "\"" (OCT | HEX | UNI | ESC | CH)* "\""
43+
CH: /[^"\\]/
44+
OCT: "\\" O ~ 1..3
45+
HEX: "\\x" X ~ 2 X*
46+
UNI: "\\u" X ~ 4 | "\\U" X ~ 8
47+
ESC: "\\" /[abefnrtv\\'"?]/
48+
O: "0".."7"
49+
X: "0".."9" | "a".."f" | "A".."F"
50+
"""
51+
52+
53+
class Record(BaseModel):
54+
pass
55+
56+
57+
class Result(Record):
58+
token: int
59+
status: str
60+
results: dict
61+
62+
63+
class ExecAsync(Record):
64+
token: int
65+
output: dict
66+
67+
68+
class StatusAsync(Record):
69+
token: int
70+
output: dict
71+
72+
73+
class NotifyAsync(Record):
74+
token: int
75+
output: dict
76+
77+
78+
class ConsoleStream(Record):
79+
msg: str
80+
81+
82+
class TargetStream(Record):
83+
msg: str
84+
85+
86+
class LogStream(Record):
87+
msg: str
88+
89+
90+
class Transform(Transformer):
91+
def lines(self, items):
92+
return [it for it in items if it is not None]
93+
94+
def line(self, items):
95+
return items[0]
96+
97+
def PROMPT(self, items):
98+
return None
99+
100+
def TN(self, items):
101+
return int(items.value)
102+
103+
def comma_results(self, items):
104+
return dict(items)
105+
106+
def result(self, items):
107+
return items
108+
109+
def KEY(self, items):
110+
return items.value.decode()
111+
112+
def tuple(self, items):
113+
return dict(items)
114+
115+
def list(self, items):
116+
return items
117+
118+
def list_kv(self, items):
119+
return items[1]
120+
121+
def C_STR(self, re):
122+
return re.value[1:-1].decode("unicode_escape")
123+
124+
def result_record(self, re):
125+
return Result(token=re[0], status=re[1].data, results=re[2])
126+
127+
def exec_async_output(self, re):
128+
return ExecAsync(token=re[0], output=re[1])
129+
130+
def status_async_output(self, re):
131+
return StatusAsync(token=re[0], output=re[1])
132+
133+
def notify_async_output(self, re):
134+
return NotifyAsync(token=re[0], output=re[1])
135+
136+
def console_stream_output(self, re):
137+
return ConsoleStream(msg=re[0])
138+
139+
def target_stream_output(self, re):
140+
return TargetStream(msg=re[0])
141+
142+
def log_stream_output(self, re):
143+
return LogStream(msg=re[0])
144+
145+
146+
parser = Lark(
147+
grammar=grammar,
148+
parser="lalr",
149+
lexer="basic",
150+
propagate_positions=False,
151+
maybe_placeholders=False,
152+
transformer=Transform(),
153+
use_bytes=True,
154+
)
155+
156+
if __debug__:
157+
from pprint import pp
158+
159+
text = (
160+
dedent(
161+
r"""
162+
0011111^running,_="\012h\'e\u0000\U00000041\tl\"\x0alo!\U0001F928"
163+
(GDB)
164+
10^done,__aa213a__=[x="1",x="2",x=[[["\\asdf\"1\x10\u0000\011'"]]]]
165+
(GDB)
166+
10^done,x={main="0x0",crimson="\"\""},y="zzz"
167+
1+stopped,y={}
168+
2*stopped,z={}
169+
3=stopped,w={}
170+
~"helloooo~!\n"
171+
@"hehehhhehe\n"
172+
&"INFO:1337"
173+
"""
174+
)
175+
.lstrip()
176+
.encode()
177+
)
178+
179+
x = parser.parse(text)
180+
pp(x)

0 commit comments

Comments
 (0)