Skip to content

Commit

Permalink
[j8] json read now uses the j8 parser, not yajl
Browse files Browse the repository at this point in the history
TODO:

- make it translate it to C++.
- get rid of remaining yajl usage, for compexport
  • Loading branch information
Andy C committed Dec 28, 2023
1 parent 540178c commit 935d5e7
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 27 deletions.
32 changes: 12 additions & 20 deletions builtin/json_ysh.py
Expand Up @@ -16,9 +16,7 @@
from frontend import typed_args
from mycpp import mylib
from mycpp.mylib import log
from ysh import cpython

import yajl
import posix_ as posix

from typing import TYPE_CHECKING
Expand All @@ -42,9 +40,11 @@ def __init__(self, mem, errfmt, is_j8):
self.mem = mem
self.errfmt = errfmt

self.stdout_ = mylib.Stdout()
self.is_j8 = is_j8
self.name = 'j8' if is_j8 else 'json' # for error messages

self.j8print = j8.Printer()
self.stdout_ = mylib.Stdout()

def Run(self, cmd_val):
# type: (cmd_value.Argv) -> int
Expand Down Expand Up @@ -124,28 +124,20 @@ def Run(self, cmd_val):
posix.strerror(e.err_num))
return 1

if self.is_j8:
#if True:
if mylib.PYTHON:
p = j8.Parser(contents)
if mylib.PYTHON:
p = j8.Parser(contents)
try:
if self.is_j8:
val = p.ParseJ8()
else:
val = p.ParseJson()
self.mem.SetPlace(place, val, blame_loc)
except error.Decode as err:
# TODO: Need to show position info
self.errfmt.Print_('%s read: %s' % (self.name, err),
blame_loc=action_loc)
return 1

else:
if mylib.PYTHON:
try:
obj = yajl.loads(contents)
except ValueError as e:
self.errfmt.Print_('json read: %s' % e,
blame_loc=action_loc)
return 1

# TODO: use token directly
val = cpython._PyObjToValue(obj)
self.mem.SetPlace(place, val, blame_loc)
self.mem.SetPlace(place, val, blame_loc)

else:
raise error.Usage(_JSON_ACTION_ERROR, action_loc)
Expand Down
7 changes: 6 additions & 1 deletion core/error.py
Expand Up @@ -213,7 +213,12 @@ class Decode(Exception):
- u"" doesn't accept \\yff
- "" doesn't accept \\yff or \\u{123456}
"""
pass
def __init__(self, msg, s, start_pos, end_pos):
# type: (str, str, int, int) -> None
self.msg = msg
self.s = s # string being decoded
self.start_pos = start_pos
self.end_pos = end_pos


class Encode(Exception):
Expand Down
21 changes: 15 additions & 6 deletions data_lang/j8.py
Expand Up @@ -51,6 +51,7 @@
from _devbuild.gen.value_asdl import (value, value_e, value_t)

from asdl import format as fmt
from core import error
from core import vm
from data_lang import pyj8
from data_lang import qsn
Expand Down Expand Up @@ -421,16 +422,20 @@ def _Eat(self, tok_id):
if self.tok_id != tok_id:
#log('position %r %d-%d %r', self.s, self.start_pos,
# self.end_pos, self.s[self.start_pos:self.end_pos])
raise AssertionError("Expected %s, got %s" %
(Id_str(tok_id), Id_str(self.tok_id)))
raise self._Error("Expected %s, got %s" % (Id_str(tok_id),
Id_str(self.tok_id)))
self._Next()

def _Error(self, msg):
# type: (str) -> error.Decode
return error.Decode(msg, self.s, self.start_pos, self.end_pos)

def _ParsePair(self):
# type: () -> Tuple[str, value_t]
if self.tok_id != Id.J8_AnyString:
raise AssertionError(Id_str(self.tok_id))
k = self.decoded
self._Next()

k = self.decoded # Save the potential string value
self._Eat(Id.J8_AnyString) # Check that it's a string
assert k is not None

self._Eat(Id.J8_Colon)

Expand Down Expand Up @@ -522,7 +527,11 @@ def _ParseValue(self):
self._Next()
return str_val

elif self.tok_id == Id.Eol_Tok:
raise self._Error('Unexpected EOF while parsing JSON')

else:
# This should never happen
part = self.s[self.start_pos:self.end_pos]
raise AssertionError('Unexpected token %s %r' %
(Id_str(self.tok_id), part))
Expand Down
2 changes: 2 additions & 0 deletions data_lang/json-errors.sh
Expand Up @@ -33,6 +33,8 @@ test-json() {
#echo OSH=$OSH
#set +o errexit

_error-case-X 1 'echo "" | json read'

_error-case-X 1 'echo { | json read'

_error-case-X 1 'echo { | j8 read'
Expand Down

0 comments on commit 935d5e7

Please sign in to comment.